MyCat分片配置测试及原理介绍

需求

建设数据表TB_TEST中数据量非常大,我们对TB_TEST表进行数据分片,分为三个数据节点

环境准备

Mycat环境搭建中,我们已经配置好了数据库,三台MySQL数据库实例分别为

192.168.0.55:3306
192.168.0.55:3307
192.168.0.55:3308

分别在这三个实例中创建数据库db1

create database db1;

配置schema.xml

schema.xml 作为MyCat中重要的配置文件之一,管理着MyCat的逻辑库、逻辑表以及对应的分片规则、DataNode以及DataSource。弄懂这些配置,是正确使用MyCat的前提

属性含义
schema标签用于定义MyCat实例中的逻辑库
table标签定义了MyCat中的逻辑表, rule用于指定分片规则,auto-sharding-long的分片规则是按ID值的范围进行分片 1-5000000 为第1片 5000001-10000000 为第2片… 具体设置我们会在第四节中讲解。
dataNode标签定义了MyCat中的数据节点,也就是我们通常说所的数据分片。
dataHost标签在mycat逻辑库中也是作为最底层的标签存在,直接定义了具体的数据库实例、读写分离配置和心跳语句。
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

	<schema name="TEST_DB" checkSQLschema="true" sqlMaxLimit="100">
		<table name="tb_test" dataNode="dn1,dn2,dn3" rule="auto-sharding-long"></table>
	</schema>
	<dataNode name="dn1" dataHost="host1" database="db1" />
	<dataNode name="dn2" dataHost="host2" database="db1" /> 
	<dataNode name="dn3" dataHost="host3" database="db1" />
	
	<dataHost name="host1" 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.0.55:3306" user="root" password="123"></writeHost>
	</dataHost>

	<dataHost name="host2" 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.0.55:3307" user="root" password="123"></writeHost>
	</dataHost> 

	<dataHost name="host3" 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.0.55:3308" user="root" password="123"></writeHost>
	</dataHost>
</mycat:schema>

配置server.xml

server.xml几乎保存了所有mycat需要的系统配置信息。最常用的是在此配置用户名、密码及权限。在system中添加UTF-8字符集设置,否则存储中文会出现问号

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
	<system>
		<property name="charset">utf8</property>
		<property name="nonePasswordLogin">0</property> 
		<property name="ignoreUnknownCommand">0</property>
		<property name="useHandshakeV10">1</property>
		<property name="removeGraveAccent">1</property>
		<property name="useSqlStat">0</property>  
		<property name="useGlobleTableCheck">0</property>  
		<property name="sqlExecuteTimeout">300</property> 
		<property name="sequnceHandlerType">1</property>
		<property name="sequnceHandlerPattern">(?:(\s*next\s+value\s+for\s*MYCATSEQ_(\w+))(,|\)|\s)*)+</property>
		<property name="subqueryRelationshipCheck">false</property> 
		<property name="sequenceHanlderClass">io.mycat.route.sequence.handler.HttpIncrSequenceHandler</property>
		<property name="processorBufferPoolType">0</property>
		<property name="handleDistributedTransactions">0</property>
		<property name="useOffHeapForMerge">0</property>
        <property name="memoryPageSize">64k</property>
		<property name="spillsFileBufferSize">1k</property>
		<property name="useStreamOutput">0</property>
		<property name="systemReserveMemorySize">384m</property>
		<property name="useZKSwitch">false</property>
		<property name="strictTxIsolation">false</property>
		<property name="useZKSwitch">true</property>
		<property name="parallExecute">0</property>
	</system>

	<user name="root" defaultAccount="true">
		<property name="password">123456</property>
		<property name="schemas">TEST_DB</property>
	</user>

	<user name="test">
		<property name="password">123456</property>
		<property name="schemas">TEST_DB</property>
	</user>

</mycat:server>

在这里我们主要配置了system的字符集<property name="charset">utf8</property> 以及两个用户

	<user name="root" defaultAccount="true">
		<property name="password">123456</property>
		<property name="schemas">TEST_DB</property>
	</user>

	<user name="test">
		<property name="password">123456</property>
		<property name="schemas">TEST_DB</property>
	</user>

启动mycat

cd /usr/local/mycat/bin
./mycat start

访问mycat

mysql -h 192.168.0.55 -P 8066 -u root -p
  1. 查看库信息
show databases;

在这里插入图片描述
2. 选择库

use  TEST_DB;
  1. 查看表信息
show tables;

在这里插入图片描述

这里显示的表是逻辑表,实际的数据库中并不存在这张表,可以使用select进行查询验证

select * from tb_test;

在这里插入图片描述
返回一个错误信息,提示我们这张表并不存在

  1. 创建表
create table tb_test(id bigint(20) not null,title varchar(100) not null,primary key(id))engine=innodb default charset=utf8;

执行完成之后,我们分别连接三个分片数据库,可以看到三个数据库中的db1库中都创建了tb_test

  1. 插入数据
insert into tb_test(id,title) values(1,'title1');
insert into tb_test(id,title) values(2,'title1');
insert into tb_test(id,title) values(3,'title1');

插入成功后,我们分别连接三个分片实例,发现上面插入的3条数据都存在了端口为3306的节点上,3307和3308节点并没有数据,出现这样的结果,是由于我们在schema.xml中配置了分片规则auto-sharding-long,这个分片规则声明在rule.xml中,我们查看rule.xml

<tableRule name="auto-sharding-long">
	<rule>
		<columns>id</columns>
		<algorithm>rang-long</algorithm>
	</rule>
</tableRule>

这里显示对表中的id列采用rang-long 的算法进行分片,而rand-long的声明是

<function name="rang-long"
		  class="io.mycat.route.function.AutoPartitionByLong">
	<property name="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

根据文件的内容,我们可以看出当id为0-500M时,数据存放在0分片节点,500M-1000M 数据存放在1分片节点,1000M-1500M 数据存放在2分片节点

下面我们通过插入指定的id进行测试

insert into tb_test(id,title) values(5000001,'title5000001');

结果这条数据存储到了3307节点上,而id为10000001

insert into tb_test(id,title) values(10000001,'title10000001');

数据存储到了3308节点上,
当id值为15000001

insert into tb_test(id,title) values(15000001,'title15000001');

mycat会提示错误信息
在这里插入图片描述
找不到符合分片算法的分片节点,当数据量到大了这个程度时,表示我们需要对分片节点进行扩展了。

原理介绍

mycat在运行过程中,拦截了用户发送的SQL语句,对SQL语句进行了特定的分析,如分片分析,路由分析,读写分离分析,缓存分析等,然后将SQL语句发送到后端真实的数据库,并将返回结果做适当的处理,最终再返回给用户
在这里插入图片描述
如图所示,user表分为dn1,dn2,dn3三个分片节点,分片字段为statusstats='0'存储在0分片节点,status='1'存储在1分片节点,status='2'存储在2分片节点。
Mycat收到一条客户端发送的SQL语句后,首先解析SQL语句涉及的表,查看此表的定义,如果该表存在分片规则,则获取SQL语句中的分片字段的值,并匹配分片函数,得到该SQL语句对应的分片列表,然后将SQL语句发送到相应的分片去执行,最后处理所有分片返回的数据,并返回给客户端;

如发送SQL为select * from user where status='0',解析查到status='0',匹配分片函数,语句发送到0分片节点中去执行,如果发送的语句为select * from user where status in ('0','1'),则SQL语句会发送到dn1,dn2两个分片节点上去执行,然后将结果合并后返回个给客户端。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心扬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值