Mycat架构简介和使用方法

Mycat介绍

官方网站:http://www.mycat.org.cn

Mycat架构

在这里插入图片描述

Mycat核心概念

  • scheme: 由它指定逻辑数据库(相当于mysql的database数据库)
  • Table: 逻辑表(相当于MySQL的table表)
  • DataNode: 真正存储数据的物理节点
  • DataHost: 存储节点所在的数据库主机(指定MySQL数据库的连接信息)
  • User: MyCat的用户(类似于MySql的用户,支持多用户)

Mycat主要解决的问题

  • 海量的数据存储
  • 查询的优化

Mycat分片策略

MyCat支持水平分片和垂直分片
  • 水平分片:一个表格的数据分割到多个节点上,按照行分割
  • 垂直分片:一个数据库中多个表格A,B,C,A存储到节点1上,B存储到节点2上,C存储到节点3上
    在这里插入图片描述
    在这里插入图片描述

MyCat通过定义表的分片来实现分片,每个表格可以捆绑一个分片规则,每个分片规则指定一个分片字段并绑定一个函数,来实现动态分片算法

  1. Schema: 逻辑库,和mysql中的database对应,一个逻辑库中定义了所包含的table
  2. Table:表,即物理数据库中存储的某一张表,和传统的数据库不同,这里的表格需要声明称存储的逻辑数据节点DataNode。在此可以指定表的分片规则;
  3. DataNode: Mycat的逻辑数据节点,是存放table的集体物理节点,也称之为分片节点,通过DataHost来关联到后端的某一个数据库上
  4. DataHost: 定义某个物理库的访问地址,用户捆绑到Datanode上

Mycat分片

配置schema.xml

schema.xml介绍

schema.xml作为Mycat中重要的配置文件之一,管理着Mycat的逻辑库、表、分片规则、DataNode以及DataHost之间的映射关系。弄懂这些配置,是正确使用Mycat的前提。

  • schema 标签用于定义MyCat实例中的逻辑库
  • Table 标签定义了MyCat中的逻辑表
  • dataNode 标签定义了MyCat中的数据节点,也就是我们通常说所的数据分片。
  • dataHost标签在mycat逻辑库中也是作为最底层的标签存在,直接定义了具体的数据库实例、读写分离配置和心跳语句。
schema.xml配置
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
	<!--
	schema : 逻辑库 name:逻辑库名称
	sqlMaxLimit:一次取多少条数据 要超过用limit xxx
	table:逻辑表
	dataNode:数据节点 对应datanode标签
	rule:分片规则,对应rule.xml
	subTables:子表
	primaryKey:分片主键 可缓存
	-->
	<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
		<!-- auto sharding by id (long) -->
		<table name="item" dataNode="dn1,dn2,dn3" rule="mod-long"
	primaryKey="ID"/>
	</schema>
	<!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743"
	/> -->
	<dataNode name="dn1" dataHost="localhost1" database="db1" />
	<dataNode name="dn2" dataHost="localhost1" database="db2" />
	<dataNode name="dn3" dataHost="localhost1" database="db3" />
	
	<!--
	dataHost : 数据主机(节点主机)
	balance:1 :读写分离 0 : 读写不分离
	writeType:0 第一个writeHost写, 1 随机writeHost写
	dbDriver: 数据库驱动 native:MySQL JDBC:Oracle、SQLServer
	switchType: 是否主动读
	1、主从自动切换 -1 不切换 2 当从机延时超过slaveThreshold值时切换为主读
	-->
	<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
	 writeType="0" dbType="mysql" dbDriver="native" switchType="1"
	 slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM1" url="192.168.24.129:3306" user="root"
		 password="root" >
		</writeHost>
	</dataHost>
</mycat:schema>

配置Server.xml

server.xml介绍

server.xml几乎保存了所有mycat需要的系统配置信息。最常用的是在此配置用户名、密码及权限。

server.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
  <system>
     <property name="defaultSqlParser">druidparser</property>
  </system>
  <user name="mycat">
     <property name="password">mycat</property>
     <property name="schemas">TESTDB</property>
  </user>
</mycat:server>

配置rule.xml

rule.xml介绍

rule.xml里面就定义了我们对表进行拆分所涉及到的规则定义。我们可以灵活的对表使用不同的分片算法,或者对表使用相同的算法但具体的参数不同。

这个文件里面主要有tableRule和function这两个标签。

在具体使用过程中可以按照需求添加tableRule和function。

rule.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat=”http://io.mycat/“ >
 	
 //表规制定义
  <tableRule name="sharding-by-intfile">
   <rule>
     <columns>sharding_id</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>
  
</mycat:rule>

tableRule 标签配置说明:

  • name 属性指定唯一的名字,用于标识不同的表规则
  • rule 标签则指定对物理表中的哪一列进行拆分和使用什么路由算法。
  • columns 内指定要拆分的列名字。
  • algorithm 使用 function 标签中的 name 属性。连接表规则和具体路由算法。当然,多个表规则
    可以连接到同一个路由算法上。 table 标签内使用。让逻辑表使用这个规则进行分片。

function 标签配置说明:

  • name 指定算法的名字。
  • class 制定路由算法具体的类名字。
  • property 为具体算法需要用到的一些属性。

十个常用的分片规则

连续分片
日期列分区法
<!--按固定时间分片-->
<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">2014-01-01</property>
  <property name="sPartionDay">10</property>
</function>

<!--按自然月分片-->
<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>

<!--按单月小时分片适合做日志,每月末,手工清理-->
<tableRule name="sharding-by-hour">
	<rule>
		<columns>create_time</columns>
		<algorithm>sharding-by-hour</algorithm>
	</rule>
</tableRule>

<function name="sharding-by-hour" class="io.mycat.route.function..LastestMonthPartition">
	<property name="splitOneDay">24</property>
</function>

配置说明:
tableRule标签:

  • columns :标识将要分片的表字段
  • algorithm :指定分片函数

function标签:

  • dateFormat :日期格式
  • sBeginDate :开始日期
  • sPartionDay :分区天数,即默认从开始日期算起,分隔10天一个分区
范围约定
<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">autopartition-long.txt</property>
</function>

配置说明:

tableRule标签:

  • columns :标识将要分片的表字段
  • algorithm :指定分片函数

function标签:

  • mapFile :指定分片函数需要的配置文件名称

autopartition-long.txt文件内容:

# range start-end ,data node index
# K=1000,M=10000.
0-500M=0         0-100  0
500M-1000M=1     101-200 1
1000M-1500M=2    201-300 2
default=0

# 或以下写法
# 0-10000000=0
# 10000001-20000000=1

优势:扩容无需迁移数据
缺点:热点数据,并发受限

离散分片
枚举法
<tableRule name="sharding-by-intfile">
	<rule>
		<columns>user_id</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">0</property>
	<property name="defaultNode">0</property>
</function>

配置说明:
tableRule标签:

  • columns :标识将要分片的表字段
  • algorithm :指定分片函数
  • function标签:
  • mapFile :指定分片函数需要的配置文件名称
  • type :默认值为0,0表示Integer,非零表示String
  • defaultNode :指定默认节点,小于0表示不设置默认节点,大于等于0表示设置默认节点,0代表节 点1。

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

partition-hash-int.txt 文件

10000=0  列等于10000 放第一个分片
10010=1=0=1

beijing=0
tianjin=1
zhanghai=2
求模法

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

<tableRule name="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>

配置说明:

tableRule标签:

  • columns :标识将要分片的表字段
  • algorithm :指定分片函数

function标签:

  • count :节点数量
字符串拆分hash解析
<tableRule name="sharding-by-stringhash">
	<rule>
		<columns>user_id</columns>
		<algorithm>sharding-by-stringhash</algorithm>
	</rule>
</tableRule>
<function name="sharding-by-stringhash" class="io.mycat.route.function.PartitionByString">
	<property name="length">512</property> <!-- zero-based -->
	<property name="count">2</property>
	<property name="hashSlice">0:2</property>
</function>

配置说明:

tableRule标签:

  • columns :标识将要分片的表字段
  • algorithm :指定分片函数

function标签:

  • length :代表字符串hash求模基数
  • count :分区数
  • hashSlice : hash预算位,即根据子字符串 hash运算

预算位 即根据子字符串中int值 hash运算 0 代表 str.length(), -1 代表 str.length()-1,大于0只代表数字自身,简单理解为substring(start,end),start为0则只表示0

“2” -> (0,2)
“1:2” -> (1,2)
“1:” -> (1,0)
“-1:” -> (-1,0)
“:-1” ->(0,-1)
“:” -> (0,0)

固定分片hash算法
<tableRule name="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>
	<property name="partitionLength">256,512</property>
</function>

配置说明:
tableRule标签:

  • columns :标识将要分片的表字段
  • algorithm :指定分片函数

function标签:

  • partitionCount :指定分片个数列表
  • partitionLength : 分片范围列表,分区长度:默认为最大2^n=1024 ,即最大支持1024分区

约束 :

count,length 两个数组的长度必须是一致的。 1024 = sum((count[i]*length[i]))

@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 };
//如果需要平均分配设置:平均分为4分片,partitionCount*partitionLength=1024
//五、一致性hash
  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);
}

如果需要平均分配设置:平均分为4分片,partitionCount*partitionLength=1024

<function name="func1" class="org.opencloudb.route.function.PartitionByLong">
	<property name="partitionCount">4</property>
	<property name="partitionLength">256</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">
	<!-- 默认是0 -->
  	<property name="seed">0</property>
 	<!-- 要分片的数据库节点数量,必须指定,否则没法分片 -->
	<property name="count">2</property>
 	<!-- 一个实际的数据库节点被映射为这么多虚拟节点,默认是160倍,也就是虚拟节点数是物理节点数
	的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>

在这里插入图片描述
一致性hash 0-2的32次方减1,预算有效解决了分布式数据的扩容问题,前1-9中id规则都多少存在数据
扩容难题,而10规则解决了数据扩容难点

编程指定
<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>

配置说明:
tableRule标签:

  • columns :标识将要分片的表字段
  • algorithm :指定分片函数

function标签:

  • startIndex :字符串截取的起始索引位置
  • size :截取的位数
  • partitionCount :分区数量
  • defaultPartition :默认分区

11010419800101
此方法为直接根据字符子串(必须是数字)计算分区号(由应用传递参数,显式指定分区号)。
例如id=05-100000002
在此配置中代表根据id中从startIndex=0,开始,截取siz=2位数字即05,05就是获取的分区,如果没
传默认分配到defaultPartition

优点:数据分布均匀,并发能力强
缺点:移植性差、扩容性差

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值