Mycat分库分表之应用指定分片
一、应用指定分片
此规则是在运行阶段有应用自主决定路由到那个分片,根据提供的字段,然后按照指定的规则,截取该字段的部分子字符串当做分片的依据,该分别方法比较灵活,适用于某个字段有几个特殊的字符串拼接而成的这种场景,例如:一个学校的学号:小学部的学号以0开头,形式为:0xxxxx(注意因为数据节点的索引是从0开始的,所以这里截取的字符串最好也是从0开始,不然第一个数据节点将会没有值存在,后面会有演示),中学部的学号以1开头,形式为1xxxxx,高中部的学号以2开头,形式为2xxxxx等,这样就不用在单独做一个字段区分学段了,只需要判断一下学号的开头就可以实现不同学段的学生分库分表储存。
说明1:子字符串分片有一个局限性,就是截取的子字符串必须是数字,而且要从截取的数字0:代表第一个数据节点,1:代表第二个数据节点,以此类推,因为数据节点的下标是从0开始的。
说明2:子字符串分片的规则是rule="sharding-by-substring"
说明3:function中的startIndex是截取子字符串的开始截取的索引位置,即从第一个位置开始截取。
说明4:function中的size是截取长度
说明5:partitionCount是分片数量,注意分片的索引从0开始,所以这里partitionCount=3,即第一个数据分片的值为0,第二个数据分片的值为1,第三个数据分片的值为2
说明6:defaultPartition是默认的数据保存的数据节点,即如果万一出现了不符合的截取数据,都会存放在这个默认数据节点上,例如现在有一个截取子字符串为5开头的数据,就会放在这个默认数据节点上。
二、准备工作
应用指定分片需求:基于逻辑库hl_logs,创建逻辑表tb_school,里面包括id,name,age等字段,其中小学部的学生id以1开头,中学部的学生id以2开头,高中部的学生id以3开头
三、配置rule.xml
<tableRule name="sharding-by-substring">
<rule>
<columns>id</columns>
<algorithm>sharding-by-substring</algorithm>
</rule>
</tableRule>
说明1:该分片方法没有在rule.xml示例中展示出来,所以需要我们手动在rule.xml文档中,添加上该规则。
<function name="sharding-by-substring" class="io.mycat.route.function.PartitionDirectBySubString">
<property name="startIndex">0</property>
<property name="size">1</property>
<property name="partitionCount">3</property>
<property name="defaultPartition">2</property>
</function>
说明2:该分片方法的function引用也没有在rule.xml的示例中展示出来,同样需要我们手动添加上function的实现
说明3:function中的startIndex是截取子字符串的开始截取的索引位置,即从第一个位置开始截取。
说明4:function中的size是截取长度
说明5:partitionCount是分片数量,注意分片的索引从0开始,所以这里partitionCount=3,即第一个数据分片的值为0,第二个数据分片的值为1,第三个数据分片的值为2
说明6:defaultPartition是默认的数据保存的数据节点,即如果万一出现了不符合的截取数据,都会存放在这个默认数据节点上,例如现在有一个截取子字符串为5开头的数据,就会放在这个默认数据节点上。
四、配置schema.xml
说明1:逻辑库为hl_logs
说明2:逻辑表为tb_school
说明3:分片规则我们改手动实现的"sharding-by-substring"
说明4:dn4对应的是dbhost1即192.168.3.90分片
说明5:dn5对应的是dbhost2即192.168.3.91分片
说明6:dn6对应的是dbhost3即192.168.3.92分片
五、配置server.xml
说明1:在之前的文章中已经将tb_logs表添加到root用户的权限中了,所以这里不需要更改即可。
六、应用指定分片测试
首先重启Mycat
登录Mycat
查看逻辑库和逻辑表
这里的tb_school只是逻辑库,而在MySQL中还并没有tb_school这个表,需要在Mycat中创建
create table tb_school(id varchar(5), name varchar(20), age int);
插入数据进行测试:这里插入一组数据进行测试:
insert into tb_school(id, name, age) values ("00001", "张三", 7);
insert into tb_school(id, name, age) values ("00002", "李四", 8);
insert into tb_school(id, name, age) values ("10001", "王五", 14);
insert into tb_school(id, name, age) values ("10002", "赵六", 15);
insert into tb_school(id, name, age) values ("20001", "侯七", 17);
insert into tb_school(id, name, age) values ("30003", "孙八", 18);
insert into tb_school(id, name, age) values ("40001", "周九", 17);
说明1:这里的id要求是字符串类型的
说明2:id虽然是字符串类型的,但是我们要截取的第一位还必须是数字,所以这中分片方式比较苛刻
说明3:第一个数据节点192.168.3.90里面保存的数据全部是id以0开头的数据
说明4:第二个数据节点192.168.3.91里面保存的数据全部是id以1开头的数据
说明5: 第三个数据节点的索引是2,所以第三个数据节点是默认数据阶段,这里面保存了id以2开头的数据,可其他不满足分片规则的数据,例如id截取第一个字符串3和4,就不满足数据分片下标0,1,2的规则,就只能进入到默认的这个数据节点中。也可以理解为默认的数据节点是兜底的分片
说明6:其实这个应用指定字符串截取的方式和枚举分片有同工异曲的效果,只是不用在单独创建一个枚举字段了。
说明7:在Mycat上进行查询的数据是,所有数据节点的全集。应用指定分片是水平分库分表的一种方式。