分库分表篇-2.2 Mycat-分片规则


前言

对Mycat 的数据节点进行配置后,想要将数据路由到不同的库,不同的表,需要对tale 配置自己的分片规则。


提示:以下是本篇文章正文内容,下面案例可供参考

一、Mycat table的分片:

Mycat是一款开源的分布式数据库中间件,支持分库分表,读写分离,高可用等功能。在Mycat中进行数据分片的基本路径是在schema.xml中定义数据节点,然后在rule.xml中定义分片规则,最后在schema.xml中的table标签中应用分片规则。

二、常用分片规则:

2.1 id 范围分片:

实现:id 在哪个区间,然后将改条数据路由到具体的库的表;
注意:超出定义的范围则报错:

使用规则为:

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

在autopartition-long.tx 配置id的范围:
在这里插入图片描述
说明: 0-10000 数据被路由到第一个节点;10001-20000 数据被路由到第二个节点;20001-30000 数据被路由到第三个节点;

2.2 id 取模分片:

实现: id%节点数量 然后 从0,到节点数量-1 进行数据分布;

使用规则为:

<tableRule name="mod-long">
	<rule>
		<columns>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>  -->
	<property name="count">2</property>
</function>

注意节点的数量要进行定义,如果配置的 节点的数量和定义的不一致则启动报错;

2.3 按照枚举值 分片:

实现:按照枚举的值进行分片:
使用规则:
schema.xml

<!--枚举 -->
<table name="meiju"  primaryKey="id" autoIncrement="true" dataNode="dn1,dn2" rule="sharding-by-intfile"  />

在rule.xml:

<tableRule name="sharding-by-intfile">
	<rule>
	<!-- 
		<columns>sharding_id</columns>
	-->
                     <!--对应枚举的列 -->
		<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>
</function>

partition-hash-int.txt 配置枚举的值:

10010=0
10011=1

说明:当name为10010时路由到第一个数据节点,当name为10011 时路由的第二个节点;

2.4 一致性hash hash 环:

实现:当key 的hash 码在hash 环中离哪个数据节点近就 路由到哪个节点:
1) 说明:
MyCat是一个开源的分布式数据库中间件,它允许将多个数据库实例组合成一个逻辑数据库集群,提供了数据分片、读写分离、故障容错等功能。在MyCat中,一致性哈希算法用于实现数据的分片和负载均衡。
一致性哈希算法是一种将数据均匀分布到不同节点的算法,同时保持了节点的动态扩展和收缩的能力。在MyCat中,使用一致性哈希算法来确定数据应该被路由到哪个节点。
具体实现上,MyCat中使用了一致性哈希环来表示节点,每个节点在环上都有一个唯一的标识。当有数据需要路由到指定节点时,MyCat会通过计算数据的哈希值,并将哈希值映射到离它最近的一个节点上。
当节点加入或移除时,只需要重新计算受影响的数据的哈希值,并将其映射到新的节点上,而不会对整个数据集进行重新分片。这使得节点的扩展和收缩变得简单高效。
总结来说,MyCat使用一致性哈希算法来实现数据的分片和负载均衡;

2)使用:

<!--枚举 -->
<table name="murmur"  primaryKey="id" autoIncrement="true" dataNode="dn1,dn2" rule="sharding-by-murmur"  />

在rule.xml:

<tableRule name="sharding-by-murmur">
	<rule>
		<columns>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倍 -->
	<!-- <property name="weightMapFile">weightMapFile</property> 节点的权重,没有指定权重的节点默认是1。以properties文件的格式填写,以从0开始到count-1的整数值也就是节点索引为key,以节点权重值为值。所有权重值必须是正整数,否则以1代替 -->
	<!-- <property name="bucketMapPath">/etc/mycat/bucketMapPath</property>
		用于测试时观察各物理节点与虚拟节点的分布情况,如果指定了这个属性,会把虚拟节点的murmur hash值与物理节点的映射按行输出到这个文件,没有默认值,如果不指定,就不会输出任何东西 -->
</function>

说明:

  • seed : seed 参数在 MyCAT 中的作用是控制一致性哈希算法 Murmur 的哈希值生成过程;
  • count: 数据节点;
  • virtualBucketTimes :每个节点 虚拟的 虚拟节点,当数据落入到虚拟节点,则可以路由到某个数据节点;

2.5 ER 分片:

实现:有父子级关联的数据可以被路由到同一个数据节点中;

在 MyCAT 中,ER(Entity-Relation)分片是一种根据实体关系进行数据分片的方式。它将相关的表按照它们之间的关联关系进行分片,使得相关数据存储在同一分片节点上,以提高查询效率。主表和子表的关系,如果按照普通的范围或者取模分片则可能造成主表的数据和子表的数据出现在不同的节点上,从而出现夸库的情况;

<table name="customer" primaryKey="id" dataNode="dn1,dn2" rule="smod-long">
	<childTable name="customer_addr" primaryKey="id" joinKey="customer_id" parentKey="id"> </childTable>
</table>

在 MyCAT 中,childTable(子表)的joinKey和parentKey是用来关联子表和主表的列。
joinKey指定了子表和主表之间关联的列,在查询时会根据这个列进行连接操作。它通常是子表中用来与主表的关联列进行匹配的列。这个列将被用于在JOIN查询中确定子表中的哪些行与主表中的行关联。
parentKey指定了主表与子表之间关联的列,在查询时也会根据这个列进行连接操作。这个列通常是子表所属主表的关联列。
例如,以下是一个示例,展示了如何在 MyCAT 中配置子表的joinKey和parentKey:

  <!-- 定义子表 -->
   <childTable name="child_table" parentColumn="parent_id" parentTables="parent_table" joinKey="child_id" parentKey="id" />

在上述示例中,joinKey属性被设置为"child_id",这意味着在查询时,MyCAT将使用子表中的"child_id"列与主表的"id"列进行连接。
而parentKey属性被设置为"id",表示主表与子表之间的关联是通过主表的"id"列与子表的"parent_id"列进行匹配。
请注意,joinKey和parentKey应该是具有相同类型的列,以允许它们进行连接操作。在配置MyCAT的时候,您可以根据实际的数据模型和业务需求来设置joinKey和parentKey,以确保正确的关联和连接操作。

2.6 库内分表:

实现:同一个数据中,按照时间进行月度分表;
使用规则为:

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

在使用按照月份分表时。需要注意一下几点:

  • 规则中,指定日期格式和开始时间:
  • 需要去手动创建不带年月的物理表:

2.7 全局表:

实现: 执行的sql 被发送到定义的所有数据节点中;
使用规则:type是global 不需要设置rule ;

<table name="student1"  primaryKey="id"  dataNode="dn2" autoIncrement="true" type="global "/>

注意:查询全局表时,会随机访问一个节点获取数据

2.8 分片表和非分片表混合使用:

实现: 数据库中,表中既有需要分片的又有不需要分片的;

  • 对分片的表进行分片规则的设置;
  • 对所有非分片的表,单独设置自己单独的数据节点;
<table name="student1"  primaryKey="id"  dataNode="dn2" autoIncrement="true" />

三、连续和离散分片对比:

3.1 连续分片:

优点:

  • 范围条件查询消耗资源少 (不需要汇总数据)
  • 扩容无需迁移数据 (分片固定)

缺点:

  • 存在数据热点的可能性
  • 并发访问能力受限于单一或少量DataNode (访问集中)

3.2 离散分片:

优点:

  • 并发访问能力增强 (负载到不同的节点)
  • 范围条件查询性能提升 (并行计算)

缺点:

  • 数据扩容比较困难,涉及到数据迁移问题
  • 数据库连接消耗比较多

四、分片键值策略参考:

选取分片键应当遵循以下几个原则:

  • 分片键应该是经常用于Where、Join操作的字段,以确保查询尽量在单个分片内执行。

  • 分片键的取值范围应当均匀,以确保数据可以平均分布到各个分片上,避免数据倾斜导致的某些分片压力过大。

  • 不要选择可能会更新的字段作为分片键。一旦分片键需要更新,那么可能会引起数据迁移,带来非常大的开销。

  • 尽量选择稳定、不易变化的字段作为分片键。如自增ID、日期等。

  • 如果有多个候选的分片键,可以考虑使用联合分片键。在查询条件中,只要包含了联合分片键中的任何一个字段,都可以定位到具体的分片。

如何选择分片键并没有定论,需要根据业务场景和数据特点进行综合考虑。如果选择不当,可能会导致数据分布不均、查询性能低下、扩展性差等问题,因此选择分片键是一个非常重要的环节。


总结

本文对mycat 的常用分片规则做了介绍,在使用时需要按照实际的业务配置不同的规则。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值