干货地带 | Mycat水平拆分之十种分片规则

Posted 瑞友科技中国事业部

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了干货地带 | Mycat水平拆分之十种分片规则相关的知识,希望对你有一定的参考价值。

笔者:魏巍   所属部门: IT一部


大家好,相信大家现在会经常用到Mycat,所以我在这里就简单的介绍一下什么是Mycat、应用场景和水平拆分的十种规则。


什么是Mycat?它是一个开源的分布式数据库系统,是一个实现了mysql协议的Server,前端用户可以把它看作是一个数据库代理,而其后端可以用MySQL原生(Native)协议与多个MySQL服务器通信,也可以用JDBC协议与大多数主流数据库服务器通信,其核心功能是分表分库。


Mycat发展到现在,已经不是一个单纯的MySQL代理了,适用的场景已经很丰富,以下是几个典型的应用场景:

1.单纯的读写分离,支持读写分离,主从切换;

2.分表分库,对于超过1000万的表进行分片,最大支持1000亿的单表分片;

3.多租户应用,每个应用一个库,但应用程序只连接Mycat,从而不改造程序本身,实现多租户化;

4.报表系统,借助于Mycat的分表能力,处理大规模报表的统计;

对于Mycat的分表,有两种拆分方法:垂直拆分和水平拆分。


下面介绍一下水平拆分的10种常用的分片规则。

一、枚举法

<tableRulename="sharding-by-intfile">

    <rule>

      <columns>user_id</columns>     标识将要分片的表字段

     <algorithm>hash-int</algorithm>  分片函数

    </rule>

  </tableRule>

<functionname="hash-int"class="io.mycat.route.function.PartitionByFileMap">

    <property name="mapFile">partition-hash-int.txt</property>配置文件名称

    <propertyname="type">0</property> 默认值为0,0表示Integer,非零表示String

    <propertyname="defaultNode">0</property>

  </function>

partition-hash-int.txt 配置: 10000=0   10010=1

defaultNode 默认节点:小于0表示不设置默认节点,大于等于0表示设置默认节点,结点为指定的值。

默认节点的作用:枚举分片时,如果碰到不识别的枚举值,就让它路由到默认节点,如果不配置默认节点(defaultNode值小于0表示不配置默认节点),碰到不识别的枚举值就会报错, like this:can't find datanode for shardingcolumn:column_name val:ffffffff 


二、固定分片hash算法

<tableRulename="rule1">

   <rule>

     <columns>user_id</columns>     标识将要分片的表字段

     <algorithm>func1</algorithm>    分片函数

   </rule>

</tableRule>

<function name="func1"class="io.mycat.route.function.PartitionByLong">

   <property name="partitionCount">2,1</property>  分片个数列表

   <propertyname="partitionLength">256,512</property>  分片范围列表

</function>

分区长度:默认为最大2^n=1024 ,即最大支持1024分区

约束 :count,length两个数组的长度必须是一致的。

1024 = sum((count[i]*length[i])).count和length两个向量的点积恒等于1024


三、范围约定

<tableRulename="auto-sharding-long">

   <rule>

     <columns>user_id</columns> 标识将要分片的表字段

     <algorithm>rang-long</algorithm>  分片函数

   </rule>

 </tableRule>

<functionname="rang-long"class="io.mycat.route.function.AutoPartitionByLong">

   <propertyname="mapFile">autopartition-long.txt</property> 配置文件名称

 </function>

autopartition-long.txt 配置:

# range start-end ,data node index

# K=1000,M=10000

0-500M=0  500M-1000M=1 1000M-1500M=2

0-10000000=0   10000001-20000000=1

所有的节点配置都是从0开始,及0代表节点1,此配置非常简单,即预先制定可能的id范围到某个分片。


四、求模法

<tableRulename="mod-long">

   <rule>

     <columns>user_id</columns>   标识将要分片的表字段

     <algorithm>mod-long</algorithm>  分片函数

   </rule>

 </tableRule>

 <function name="mod-long"class="io.mycat.route.function.PartitionByMod">

  <!-- how many data nodes -->

   <property name="count">3</property>

 </function>

配置说明:

此种配置非常明确即根据id与count(你的结点数)进行求模预算,相比方式1,此种在批量插入时需要切换数据源,id不连续。


五、日期列分区法

<tableRulename="sharding-by-date">

     <rule>

       <columns>create_time</columns>   标识将要分片的表字段

        <algorithm>sharding-by-date</algorithm>  分片函数

     </rule>

  </tableRule>

<function name="sharding-by-date"class="io.mycat.route.function..PartitionByDate">

  <property name="dateFormat">yyyy-MM-dd</property>

   <property name="sBeginDate">2014-01-01</property>

   <property name="sPartionDay">10</property>

 </function>

配置中配置了开始日期,分区天数,即默认从开始日期算起,分隔10天一个分区。


六、通配取模

<tableRulename="sharding-by-pattern">

     <rule>

        <columns>user_id</columns>    标识将要分片的表字段

       <algorithm>sharding-by-pattern</algorithm>   分片函数

     </rule>

  </tableRule>

<functionname="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>

partition-pattern.txt 配置:

# id partition range start-end ,datanode index

###### first host configuration

1-32=0  33-64=1 65-96=2  97-128=3

######## second host configuration

129-160=4  161-192=5 193-224=6  225-256=7  0-0=7

配置文件中,1-32 即代表id%256后分布的范围,如果在1-32则在分区1,其他类推,如果id非数字数据,则会分配在defaoultNode 默认节点。

七、ASCII码求模通配

<tableRulename="sharding-by-prefixpattern">

     <rule>

        <columns>user_id</columns>  标识将要分片的表字段

        <algorithm>sharding-by-prefixpattern</algorithm>  分片函数

     </rule>

  </tableRule>

<functionname="sharding-by-pattern"class="io.mycat.route.function.PartitionByPrefixPattern">

   <property name="patternValue">256</property> 求模基数

   <property name="prefixLength">5</property> ASCII 截取的位数

   <propertyname="mapFile">partition-pattern.txt</property>  配置文件名称

 </function>

partition-pattern.txt配置:

# range start-end ,data node index

# ASCII  48-57=0-9  64、65-90=@、A-Z   97-122=a-z

###### first host configuration

1-4=0  5-8=1  9-12=2  13-16=3

###### second host configuration

17-20=4  21-24=5 25-28=6  29-32=7  0-0=7

配置文件中,1-32 即代表id%256后分布的范围,如果在1-32则在分区1,其他类推。

八、编程指定

<tableRulename="sharding-by-substring">

     <rule>

        <columns>user_id</columns>   标识将要分片的表字段

       <algorithm>sharding-by-substring</algorithm>  分片函数

     </rule>

  </tableRule>

<functionname="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>

此方法为直接根据字符子串(必须是数字)计算分区号(由应用传递参数,显式指定分区号)。

例如id=05-100000002

在此配置中代表根据id中从startIndex=0,开始,截取siz=2位数字即05,05就是获取的分区,如果没传默认分配到defaultPartition


九、字符串拆分hash解析

<tableRulename="sharding-by-stringhash">

     <rule>

        <columns>user_id</columns>  标识将要分片的表字段

       <algorithm>sharding-by-stringhash</algorithm>  分片函数

     </rule>

  </tableRule>

<functionname="sharding-by-substring"class="io.mycat.route.function.PartitionByString">

   <property name=length>512</property>  字符串hash求模基数

   <property name="count">2</property> 分区数

   <property name="hashSlice">0:2</property> hash预算位

 </function>


十、一致性hash

<tableRulename="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>  默认是0

     <property name="count">2</property> 要分片的数据库节点数量,必须指定,否则没法分片

     <property name="virtualBucketTimes">160</property>一个实际的数据库节点被映射为这么多虚拟节点,默认是160倍,也就是虚拟节点数是物理节点数的160倍

<!--<propertyname="weightMapFile">weightMapFile</property>节点的权重,没有指定权重的节点默认是1。以properties文件的格式填写,以从0开始到count-1的整数值也就是节点索引为key,以节点权重值为值。所有权重值必须是正整数,否则以1代替 -->

<!--<propertyname="bucketMapPath">/etc/mycat/bucketMapPath</property>用于测试时观察各物理节点与虚拟节点的分布情况,如果指定了这个属性,会把虚拟节点的murmurhash值与物理节点的映射按行输出到这个文件,没有默认值,如果不指定,就不会输出任何东西 -->

</function>


一致性hash预算有效解决了分布式数据的扩容问题,前1-9中id规则都多少存在数据扩容难题,而10规则解决了数据扩容难点。


以上是关于干货地带 | Mycat水平拆分之十种分片规则的主要内容,如果未能解决你的问题,请参考以下文章

mycat

mycat

MyCat水平分库

《SQL与数据库基础》21. 分库分表

mycat分片规则

mycat1.6.5分片(字符串拆分hash)