在数据切分处理中,特别是水平切分中,中间件最重要的两个处理过程就是数据的切分、数捤的聚和。选择合适的切分规则,至关重要,因为它决定了后续数据聚和的难易程度,甚至可以避免跨库的数据聚合处理。
分片规则配置文件rule.xml
rule.xml 里面就定义了我们对表进行拆分所涉及到的规则定义。我们可以灵活的对表使用不同的分片算法,或者对表使用相同的算法但具体的参数不同。这个文件里面主要有 tableRule 和 function 这丟个标签。在具体使用过程中可以按照需求添加 tableRule 和 function。
tableRule标签
这个标签定义了表规则。
定义的表规则,在 schema.xml的table标签中可以用rule属性指定规则:
<tableRule name="rule1">
<rule>
<columns>id</columns>
<algorithm>func1</algorithm>
</rule>
</tableRule>
name 属性指定唯一的名字,用于标示不同的表规则。
内嵌的 rule 标签则指定对物理表中的哪一列进行拆分和使用什么路由算法。
columns 指定要拆分的列名字。
algorithm 使用 function 标签中的name 属性。连接表规则和具体路由算法。当然,多个表规则可以连接到同一个路由算法上。table 标签内使用。让逻辑表使用这个规则进行分片。
function标签
<function name="hash-int" class="org.opencloudb.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property>
</function>
name 指定算法的名字。
class 指定路由算法具体的类名字。
property 为具体算法需要用到的一些属性。
一、枚举法
* defaultNode 默认节点:小于0表示不设置默认节点,大于等于0表示设置默认节点,结点为指定的值
*
默认节点的作用:枚举分片时,如果碰到不识别的枚举值,就让它路由到默认节点
* 如果不配置默认节点(defaultNode值小于0表示不配置默认节点),碰到
* 不识别的枚举值就会报错,
* like this:can't find datanode for sharding column:column_name val:ffffffff
*/
二、固定分片hash算法
1024 = sum((count[i]*length[i])). count和length两个向量的点积恒等于1024
@Test public void testPartition() { // 本例的分区策略:希望将数据水平分成3份,前两份各占25%,第三份占50%。(故本例非均匀分区) // |<---------------------1024------------------------>| // |<----256--->|<----256--->|<----------512---------->| // | partition0 | partition1 | partition2 | // | 共2份,故count[0]=2 | 共1份,故count[1]=1 | int[] count = new int[] { 2, 1 }; int[] length = new int[] { 256, 512 }; PartitionUtil pu = new PartitionUtil(count, length); // 下面代码演示分别以offerId字段或memberId字段根据上述分区策略拆分的分配结果 int DEFAULT_STR_HEAD_LEN = 8; // cobar默认会配置为此值 long offerId = 12345; String memberId = "qiushuo"; // 若根据offerId分配,partNo1将等于0,即按照上述分区策略,offerId为12345时将会被分配到partition0中 int partNo1 = pu.partition(offerId); // 若根据memberId分配,partNo2将等于2,即按照上述分区策略,memberId为qiushuo时将会被分到partition2中 int partNo2 = pu.partition(memberId, 0, DEFAULT_STR_HEAD_LEN); Assert.assertEquals(0, partNo1); Assert.assertEquals(2, partNo2); }
三、范围约定
四、求模法
五、日期列分区法
Assert.assertEquals(true, 0 == partition.calculate("2014-01-01"));
Assert.assertEquals(true, 0 == partition.calculate("2014-01-10"));
Assert.assertEquals(true, 1 == partition.calculate("2014-01-11"));
Assert.assertEquals(true, 12 == partition.calculate("2014-05-01"));
六、通配取模
String idVal = "0";
Assert.assertEquals(true, 7 == autoPartition.calculate(idVal));
idVal = "45a";
Assert.assertEquals(true, 2 == autoPartition.calculate(idVal));
七、ASCII码求模通配
* ASCII编码:
* 48-57=0-9阿拉伯数字
* 64、65-90=@、A-Z
* 97-122=a-z
*
*/
String idVal="gf89f9a";
Assert.assertEquals(true, 0==autoPartition.calculate(idVal));
idVal="8df99a";
Assert.assertEquals(true, 4==autoPartition.calculate(idVal));
idVal="8dhdf99a";
Assert.assertEquals(true, 3==autoPartition.calculate(idVal));
八、编程指定
九、字符串拆分hash解析
/**
* "2" -> (0,2)<br/>
* "1:2" -> (1,2)<br/>
* "1:" -> (1,0)<br/>
* "-1:" -> (-1,0)<br/>
* ":-1" -> (0,-1)<br/>
* ":" -> (0,0)<br/>
*/
public class PartitionByStringTest { @Test public void test() { PartitionByString rule = new PartitionByString(); String idVal=null; rule.setPartitionLength("512"); rule.setPartitionCount("2"); rule.init(); rule.setHashSlice("0:2"); // idVal = "0"; // Assert.assertEquals(true, 0 == rule.calculate(idVal)); // idVal = "45a"; // Assert.assertEquals(true, 1 == rule.calculate(idVal)); //last 4 rule = new PartitionByString(); rule.setPartitionLength("512"); rule.setPartitionCount("2"); rule.init(); //last 4 characters rule.setHashSlice("-4:0"); idVal = "aaaabbb0000"; Assert.assertEquals(true, 0 == rule.calculate(idVal)); idVal = "aaaabbb2359"; Assert.assertEquals(true, 0 == rule.calculate(idVal)); }
十、一致性hash
转载请注明:左手代码右手诗 » Mycat中的10种分片规则