Mycat 常用分片规则

分表分库原则

分表分库虽然能解决大表对数据库系统的压力,但它并不是万能的,也有一些不利之处,因此首要问题是分不分库,分哪些库,什么规则分,分多少分片,一般而言有以下原则:

  1. 能不分就不分,1000万以内的表,不建议分片,通过合适的索引,读写分离等方式,可以很好的解决性能问题。
  2. 分片数量尽量少,分片尽量均匀分布在多个DataHost上,因为一个查询SQL跨分片越多,则总体性能越差,虽然要好于所有数据在一个分片的结果,只在必要的时候进行扩容,增加分片数量。
  3. 分片规则需要慎重选择,分片规则的选择,需要考虑数据的增长模式,数据的访问模式,分片关联性问题,以及分片扩容问题,常用的分片策略为范围分片,枚举分片,一致性Hash分片,这几种分片都有利于扩容。
  4. 尽量不要在一个事务中的SQL跨越多个分片,分布式事务一直是个不好处理的问题。
  5. 查询条件尽量优化,尽量避免select * 的方式,大量数据结果集下,会消耗大量带宽和CPU资源,查询尽量避免返回大量结果集,并且尽量为频繁使用的查询语句建立索引。

这里特别强调一下分片规则的选择问题,如果某个表的数据有明显的时间特征,比如订单、交易记录等,则他们通常比较合适用时间范围分片,因为具有时效性的数据,我们往往关注其近期的数据,查询条件中往往带有时间字段进行过滤,比较好的方案是,当前活跃的数据,采用跨度比较短的时间段进行分片,而历史性的数据,则采用比较长的跨度存储。
总体上来说,分片的选择是取决于频繁的查询SQL 的条件,因为不带任何Where 语句的查询 SQL,会便利所有的分片,性能相对差,因此这种SQL 越多,对系统的影响越大,所以我们要尽量避免这种SQL 的产生。

ER表

Mycat 中的ER 表是基于E-R 关系的数据分片策略,子表的记录与所关联的父表记录存放在同一个数据分片上,保证数据Join 不会跨库操作。
ER分片是解决跨分片数据join 的一种很好的思路,也是数据切分规划的一条重要规则。

<table name="customer" primaryKey="customer_id" dataNode="dn1,dn2" rule="shardingby-intfile">        
	<childTable name="orders" primaryKey="order_id" joinKey="customer_id" parentKey="customer_id" />                  
</table>

全局表

一个真实的业务系统中,往往存在大量的类似字典表的表,这些表基本上很少变动。
业务表往往需要和字典表Join查询,当业务表因为规模而进行分片以后,业务表与字典表之间的关联跨库了,在Mycat中通过表冗余来解决这类表的join,即它的定义中指定的dataNode上都有一份该表的拷贝(即全局表)

<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" /> 

分片枚举

通过在配置文件中配置可能的枚举id,自己配置分片,本规则适用于特定的场景,比如有些业务需要按照省份或区县来做保存,而全国省份区县固定的,这类业务使用本条规则,配置如下:

<tableRule name="sharding-by-enum">     
	<rule>         
		<columns>id</columns>         
		<algorithm>enum_func</algorithm>     
	</rule> 
</tableRule> 
<function name="enum_func" class="io.mycat.route.function.PartitionByFileMap">     
	<property name="mapFile">sharding-by-enum.txt</property>
	<property name="type">0</property>    		    
	<property name="defaultNode">0</property> 
</function> 
  1. 算法实现类为:io.mycat.route.function.PartitionByFileMap
  2. mapFile 标识配置文件名称;
  3. type 默认值为0,0 表示Integer,非零表示String;
  4. defaultNode defaultNode 默认节点:小于0 表示不设置默认节点,大于等于0 表示设置默 认节点为第几个数据节点。 默认节点的作用:枚举分片时,如果碰到不识别的枚举值,就让它路由到默认节点如果不配置默认节点(defaultNode 值小于0 表示不配置默认节点),碰到不识别的枚举值就会报错。

sharding-by-enum.txt 放置在conf/下,配置内容示例

#字段值为10000的放到0号数据节点 
10000=0     
10010=1 

范围分片

<tableRule name="range-sharding">     
	<rule>         
		<columns>id</columns>         
		<algorithm>rang-long</algorithm>     
	</rule> 
</tableRule> 
<function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong">     
	<property name="mapFile">range-partition.txt</property>
	<property name="defaultNode">0</property> 
</function>

mapFile 代表配置文件,在conf目录下
defaultNode 超过范围后的默认节点。所有的节点配置都是从0 开始,及0 代表节点1。
mapFile中的定义示例

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

或者

0-10000000=0 
10000001-20000000=1

按日期范围分片

<tableRule name="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">2020-01-01</property>     
	 <property name="sEndDate">2021-01-02</property>     
	 <property name="sPartionDay">10</property> 
 </function>

columns :标识将要分片的表字段
algorithm :分片函数
dateFormat :日期格式
sBeginDate :开始日期
sEndDate:结束日期
sPartionDay :分区天数,即默认从开始日期算起,分隔10 天一个分区
注意:
当sBeginDate,sEndDate 都有指定时,此时表的dataNode 数量的>=这个时间段算出的分片数,否则启动时会异常。如果配置了sEndDate 则代表数据达到了这个日期的分片后循环从开始分片插入

没有指定 sEndDate 的情况 数据分片将依次存储到dataNode上,数据分片随时间增长,所需的dataNode数也随之增 长,当超出了为该表配置的dataNode数时,也会出现异常。

自然月分片

按月份列分区,每个自然月一个分片

<tableRule name="sharding-by-month">     
	<rule>         
		<columns>create_time</columns>         
		<algorithm>sharding-by-month</algorithm>     
	</rule> 
</tableRule> 
<function name="sharding-by-month" class="io.mycat.route.function.PartitionByMonth">     
	<property name="dateFormat">yyyy-MM-dd</property>     
	<property name="sBeginDate">2014-01-01</property> 
</function>

columns: 分片字段,字符串类型
dateFormat : 日期字符串格式,默认为yyyy-MM-dd
sBeginDate : 开始日期,无默认值
sEndDate:结束日期,无默认值
节点从0 开始分片
注意:
不指定sBeginDate、sEndDate时节点数量必须是12 个,对应1 月~12 月

仅指定sBeginDate时从该时间按月递增,无最大节点

取模分片

此规则为对分片字段进行十进制运算,来分片数据

<tableRule name="mod-sharding">     
	<rule>         
		<columns>id</columns>         
		<algorithm>mod-fun</algorithm>     
	</rule>
</tableRule> 
<function name="mod-fun" class="io.mycat.route.function.PartitionByMod"> 
	  <property name="count">3</property> 
</function>

count 指明dataNode 的数量,是求模的基数

取模范围分片

此种规则是取模运算与范围约束的结合,主要为了后续数据迁移做准备,即可以自主决定取模 后数据的节点 分布

<tableRule name="sharding-by-pattern">    
	<rule>        
		<columns>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>

partition-pattern.txt

#余数为1-32的放到数据节点01-32=0          
33-64=1 
65-96=2 
97-128=3 
129-160=4 
161-192=5 
193-224=6 
225-256=7

范围取模分片

先进行范围分片计算出分片组,组内再求模。
优点可以避免扩容时的数据迁移,又可以一定程度上避免范围分片的热点问题。综合了范围分片和求模分片的优点,分片组内使用求模可以保证组内数据比较均匀,分片组之间是范围分片 可以兼顾范围查询。
好事先规划好分片的数量,数据扩容时按分片组扩容,则原有分片组的数据不需要迁移。由 于分片组内数据比 较均匀,所以分片组内可以避免热点数据问题。

<tableRule name="auto-sharding-rang-mod">     
	<rule>        
		<columns>id</columns>         
		<algorithm>rang-mod</algorithm>     
	</rule> 
</tableRule> 
<function name="rang-mod" class="io.mycat.route.function.PartitionByRangeMod">     
	<property name="mapFile">partition-range-mod.txt</property>     <property name="defaultNode">21</property> 
</function>

partition-range-mod.txt 以下配置一个范围代表一个分片组,=号后面的数字代表该分片组所拥有的分片的数量

//代表有5个分片节点 
0-200M=5      
200M1-400M=1 
400M1-600M=4 
600M1-800M=4 
800M1-1000M=6 

一致性hash

一致性hash 算法有效解决了分布式数据的扩容问题

<tableRule name="sharding-by-murmur">     
	<rule>         
		<columns>id</columns>         
		<algorithm>murmur</algorithm>     
	</rule> 
</tableRule> 
<function name="murmur" class="io.mycat.route.function.PartitionByMurmurHash">    
	<!-- 默认是0-->     
	<property name="seed">0</property>
  	<!-- 要分片的数据库节点数量,必须指定,否则没法分片-->
  	<property name="count">2</property>      	
    <!-- 一个实际的数据库节点被映射为多少个虚拟节点,默认是160 -->
    <property name="virtualBucketTimes">160</property>      	
    <!--     
    <property name="weightMapFile">weightMapFile</property>     
    节点的权重,没有指定权重的节点默认是1。以properties 文件的格式填写,以从0 开始到 count-1 的整数值也就是节点索引为key,以节点权重值为值。所有权重值必须是正整数,否则以1 代替
    -->     
    <!--     
    <property name="bucketMapPath">/etc/mycat/bucketMapPath</property>     
    用于测试时观察各物理节点与虚拟节点的分布情况,如果指定了这个属性,会把虚拟节点的 murmur hash 值与物理节点的映射按行输出到这个文件,没有默认值,如果不指定,就不会输出任何东西
    -->
</function>  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值