rule.xml 的 tableRule 标签配置表的分片规则如下:
<tableRule name="rule">
<rule>
<columns>id</columns>
<algorithm>rule1</algorithm>
</rule>
</tableRule>
name指定分片规则名字,唯一性;
columns指定用于分片的mysql实体表的字段,
algorithm指定使用的分片算法,取自标签定义的函数,函数的实现是编写在java代码中的
rule.xml 的 function 标签配置表的分片算法如下:
<function name="rule1" class="io.mycat.route.function.PartitionByHashMod" >
<property name="count">5</property>
</function>
name 指定算法的名字,供algorithm引用
class 制定路由算法具体的类名字
property 为具体算法需要用到的一些属性
<tableRule name="sharding-by-intfile">
<rule>
<columns>name</columns>
<algorithm>hash-int</algorithm>
</rule>
</tableRule>
<function name="hash-int" class="io.mycat.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property>
<property name="type">1</property>
<property name="defaultNode">0</property>
</function>
partition-hash-int.txt 配置:
10000=0
适用提前规划好分片字段某个范围属于哪个分片
<tableRule name="auto-sharding-long">
<rule>
<columns>user_id</columns>
<algorithm>rang-long</algorithm>
</rule>
</tableRule>
<function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong">
<property name="mapFile">auto-sharding-long.txt</property>
<property name="defaultNode">0</property>
</function>
auto-sharding-long.txt 配置:
2000001-4000000=1
0-2000000=0
4000001-8000000=2
defaultNode 超过范围后的默认节点。
这个主要针对非整数字段,通过哈希算法得到一个整数值,然后对分片数量 count 进行取模分片,就可以得到分片位置。
分片没有简单取模算法均匀,因为存在 hash 重复的情况,两个相同的数据进行 hash 运算后的数值是一样的,那么取模后得出来的分片位置也就一样,会被储存到同一分片,比如有 100 条订单记录,其中 90 条是 A 的,其他分别是B、C 的,如果根据用户名字段进行哈希取模分片,那么 A 的 90 条记录都会集中在同一分片中,只有其它 10 条在别的分片中,造成数据存储不均匀。
<tableRule name="users">
<rule>
<columns>users_Fname</columns>
<algorithm>hash-mod</algorithm>
</rule>
</tableRule>
<function name="hash-mod" class="io.mycat.route.function.PartitionByHashMod">
<!-- 要分片的数据库节点数量,必须指定,否则没法分片 -->
<property name="count">3</property>
</function>
适用于根据整数字段进行分片,取模的值对应分片库的序号,比如某条记录的id=100, mod 3 = 1,那这条记录就在分片db2(分片节点的序号从0开始)上
<tableRule name="mod-long-2_id">
<rule>
<columns>id</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
<function name="mod-long"
class="io.mycat.route.function.PartitionByMod">
<property name="count">2</property>
</function>
分片算法根据列进行分片的,也可能通过字符串来进行分片,例如,需要对 ABCDEF 这个字符串的前三位进行分片计算,其计算过程如下图:
逻辑顺序:
对指定的字符串范围分别进行 ascii 码计算并求和,然后对配置的求模基数进行取模计算,最后根据 mapFile 里配置的取值范围与数据节点索引的映射关系得出分片的数据节点。因此,mapFile 需要配置所有可能的取值范围,否则找不到对应的数据节点就会报错。
<tableRule name="sharding-by-prefix-pattern_login_name">
<rule>
<columns>login_name</columns>
<algorithm>sharding-by-prefix-pattern</algorithm>
</rule>
</tableRule>
<function name="sharding-by-prefix-pattern"
class="io.mycat.route.function.PartitionByPrefixPattern">
<property name="mapFile">prefix-partition-pattern.txt</property>
<property name="patternValue">128</property>
<property name="prefixLength">2</property>
</function>
<tableRule name="sharding-by-pattern">
<rule>
<columns>user_id</columns>
<algorithm>sharding-by-pattern</algorithm>
</rule>
</tableRule>
<function name="sharding-by-pattern" class="io.mycat.route.function.PartitionByPattern">
<property name="patternValue">256</property>
<property name="defaultNode">2</property>
<property name="mapFile">partition-pattern.txt</property>
</function>
# id partition range start-end ,data node index
###### first host configuration
1-32=0
33-64=1
65-96=2
1-32 即代表 id % 256 后分布的范围,如果在 1-32 则在分区 1,其他类推,如果 id 不为 int 则分配到 defaultNode 配置的分区中
该方法的指定字段必须为数字,size 为截取的位数,partitionCount 为分区个数,defaultPartition 为默认节点,例如 id = 05-100000002,在此配置中代表根据 id 中从 startIndex = 0,开始,截取 siz = 2 位数字即 05,05 就是获取的分区,如果没传默认分配到 defaultPartition。
<tableRule name="sharding-by-substring">
<rule>
<columns>user_id</columns>
<algorithm>sharding-by-substring</algorithm>
</rule>
</tableRule>
<function name="sharding-by-substring" class="io.mycat.route.function.PartitionDirectBySubString">
<property name="startIndex">0</property> <!-- zero-based -->
<property name="size">2</property>
<property name="partitionCount">8</property>
<property name="defaultPartition">0</property>
</function>
一致性hash 预算有效解决了分布式数据的扩容问题。
<tableRule name="sharding-by-murmur">
<rule>
<columns>user_id</columns>
<algorithm>murmur</algorithm>
</rule>
</tableRule>
<function name="murmur" class="io.mycat.route.function.PartitionByMurmurHash">
<property name="seed">0</property>
<property name="count">2</property>
<property name="virtualBucketTimes">160</property>
<property name="weightMapFile">weightMapFile</property>
<property name="bucketMapPath">/etc/mycat/bucketMapPath</property>
</function>
范围取模分片的优点在于,既拥有范围分片的固定范围数据不做迁移的优点,也拥有了取模分片对于热点数据均匀分布的优点,综合了范围分片和取模分片的优点,分片组内使用求模可以保证组内数据比较均匀,分片组之间是范围分片,可以兼顾范围查询,最好事先规划好分片的数量,数据扩容时按分片组扩容,则原有分片组的数据不需要迁移。由于分片组内数据比较均匀,所以分片组内可以避免热点数据问题。
id
rang-mod
partition-range-mod.txt
21
defaultNode:默认节点,小于 0 表示不设置默认节点,大于等于 0 表示设置默认节点,如果超出配置的范围,则使用默认节点。
partition-range-mod.txt 配置:
# 以下配置一个范围代表一个分片组,=号后面的数字代表该分片组所拥有的分片的数量。
# range start-end ,data node group size
0-200M=5 //代表有 5 个分片节点
200M1-400M=1
400M1-600M=4
600M1-800M=4
800M1-1000M=6
这里需要注意:如上0-200M 存入到 5 个分片中,开始范围-结束范围=该分片组有多少个分片。如果超过配置范围需要增加分片组。