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

首先,需要你准备俩个库。
本篇db1的连接地址为192.168.247.140:3000 db2的为192.168.247.140:3001 并在俩个库新建一个test表

DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

修改配置文件

server.xml默认即可,只需要知道登录mycat的用户名和密码。

修改schema.xml

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
	<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
		<table name="test" primaryKey="id" dataNode="dn1,dn2" rule="mod-long" />
	</schema>

	<dataNode name="dn1" dataHost="localhost1" database="db1" />
	<dataNode name="dn2" dataHost="localhost2" database="db2" />

	<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.247.140:3000" user="root" password="password" />
	</dataHost>
	<dataHost name="localhost2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM2" url="192.168.247.140:3001" user="root" password="password" />
	</dataHost>
</mycat:schema>

修改rule.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/">
	<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">0</property>
	</function>
</mycat:rule>

mapFile:代表配置文件路径
defaultNode:超过范围后的默认节点顺序号,节点从0 开始。

打开conf目录下的partition-range-mod.txt

# range start-end ,data node group size
0-1M=1
1M1-2M=1

M表示一万,第一行是0到1万分配一个节点
M1表示万零一(10001),第二行表示10001到20000分配一个节点。
=号后面的数字代表该分片组所拥有的分片的数量。比如你有5个节点,设置一行=1,那你就剩下4个节点,剩下的配置的和只能小于等于4。

重启mycat

# ./mycat restart
# mysql -h ip地址 -uroot -p123456 -P8066
mysql> use TESTDB
mysql> INSERT INTO test (id, name)VALUES ('9999', 'weikaixxxxxx');
mysql> INSERT INTO test (id, name)VALUES ('10000', 'weikaixxxxxx');
mysql> INSERT INTO test (id, name)VALUES ('10001', 'weikaixxxxxx');
mysql> INSERT INTO test (id, name)VALUES ('20000', 'weikaixxxxxx');

mysql innodb碎片整理 mysql 分片扩容_数据

当超过20000时,会添加到默认节点中,0表示节点1,1表示节点2

mysql innodb碎片整理 mysql 分片扩容_mysql innodb碎片整理_02

扩容

新建第三个库和一张test表,表内有id和name字段

mysql> create database db3;
mysql> use db3

DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

修改schema.xml,增加一个节点,注意命名,名字要改对了!

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
	<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
		<table name="test" primaryKey="id" dataNode="dn1,dn2,dn3" rule="auto-sharding-rang-mod" />
	</schema>

	<dataNode name="dn1" dataHost="localhost1" database="db1" />
	<dataNode name="dn2" dataHost="localhost2" database="db2" />
	<dataNode name="dn3" dataHost="localhost3" database="db3" />

	<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.247.140:3000" user="root" password="password" />
	</dataHost>
	<dataHost name="localhost2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM2" url="192.168.247.140:3001" user="root" password="password" />
	</dataHost>
	<dataHost name="localhost3" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM3" url="192.168.247.140:3002" user="root" password="password" />
	</dataHost>
</mycat:schema>

修改partition-range-mod.txt
我们现在有三个节点了,0到10000我分配俩个节点。

# range start-end ,data node group size
0-1M=2
1M1-2M=1

重启mycat,重启的过程去清空俩个表

# ./mycat restart
# mysql -h ip地址 -uroot -p123456 -P8066
mysql> use TESTDB
mysql> INSERT INTO test (id, name)VALUES ('9999', 'weikaixxxxxx');
mysql> INSERT INTO test (id, name)VALUES ('10000', 'weikaixxxxxx');
mysql> INSERT INTO test (id, name)VALUES ('10001', 'weikaixxxxxx');
mysql> INSERT INTO test (id, name)VALUES ('20000', 'weikaixxxxxx');

mysql innodb碎片整理 mysql 分片扩容_数据_03


0-1M=2分配到了db1和db2,1M1-2M=1分配到了db3。

如果只是单一的求模分片的话,会有一个扩容的问题,就是扩容时,需要做数据迁移,也就是你得把所有库导出来,再导入,使数据均匀(如果导入时报错呢?)。
为什么要这样?当你有俩个节点都达到性能瓶颈了,你再加一个节点,mycat还是会写入那俩个已经不堪重负的节点,也就是你新增的节点并没有起到多大作用。

如果只是单一的指定范围分片,对并发又不友好。因为0到10000,都是在写进那个节点,其它节点空闲。

所以,范围求模分片就是它俩的结合体。0到10000,可以分配多个节点,在并发写入时可以分摊压力,新增节点时,只要配置一行从几到几就能完成扩容。我这里只加了一个db3节点,如果再加一个db4,分配俩个节点,就会和db1和db2一样均衡了。