文章目录
- 1.固定Hash算法分片的概念
- 1.1.固定Hash算法的概念
- 1.2.固定Hash算法是如何将数据路由到分片节点的
- 2.使用固定Hash算法分片对某张表进行水平拆分
- 2.1.在所有的分片节点中创建表结构
- 2.2.配置Mycat实现固定Hash算法分片的水平分表
- 2.2.1.配置Schema配置文件
- 2.2.2.配置Rule分片规则配置文件
- 2.2.3.配置Server配置文件
- 2.2.4.重启Mycat
- 2.3.写入数据观察分片效果
1.固定Hash算法分片的概念
1.1.固定Hash算法的概念
固定Hash算法类似于十进制的求模运算,但是固定Hash算法是为二进制进行运算的,固定Hash运算会将依据的字段转换成耳机10位的二进制数字,然后与二进制1111111111进行位&运算。
位于运算时这个样子的:例如8的二进制是1000,7的二进制是0111,求1000和0111的位&运算,计算方式就是按照第一个二进制的每一位与第二个二进制的每一位进行相乘,如1*0=0 0*1=0 0*1=0 0*1=0
,最后得出1000和0111的位&运算是0000。
固定Hash算法会将依据的字段内容转换成二进制数,然后与1111111111进行位运算,任何二进制数与1111111111进行位运算最终的结果都会在0000000000和1111111111之间,转换成十进制数也就是0-1023。
我们可以将分片策略设置0-255之间划分到分片1,256-512之间划分到分片2,512-1023划分到分片3,当依据字段被固定Hash转换成2进制数并且位运算完后,得到一个十进制数时,根据十进制数所在的分片,将数据写入到对应的分片节点中。
如下图所示,当字段值为1时,转换成二进制数与10个1进行位运算,最后在转换成十进制数,刚好也是1,0~255之间划分到分片1上,此时这条数据就会被划分到分片1节点上。
固定Hash算法的特点:
- 如果是取模分片,连续的值可能会分配到不同的分片中,而固定Hash算法会将连续的值可能分配到同一个分片中,降低事务处理的难度。
- 可以均匀的分配,也可以非均匀分配。
- 分片字段必须是数字类型。
1.2.固定Hash算法是如何将数据路由到分片节点的
我们会在定义分片策略时,一共有3个分片节点,例如定义第一个节点存储位运算结果0-255之间的数据,第二个节点处理256-511之间的数据,第三个节点处理512到1023之间的数据,此时前两个节点分别处理256个数组。,第三个节点则处理512个数组。
在0-255之间数组的结构中,会记录上第一个分片节点的ID0,255-511之间的数组的结构中,记录第二个分片节点的ID1,512-1023之间的数组结构中,记录第三个分片节点的ID2。
例如当字段值为515,经过固定Hash算法运算,将515转换成二进制数,与1023的二进制数进行位运算,最后的出来位运算的结果是十进制数515,515位于512-1023数组之间,此时就会拿导512-1023数组对应的分片ID号,然后将这条数据写入到对应的分片节点中。
2.使用固定Hash算法分片对某张表进行水平拆分
需求:目前有一张tb_longhash 表,表中的id一列的值是数字类型,我们按照这个字段进行固定Hash算法分片。
2.1.在所有的分片节点中创建表结构
分片依旧是2个,还是之前垂直分库分表时使用的两套双主双从集群。
#在分片1节点中创建表结构
[root@mysql-1 ~]# mysql -uroot -p123456 -P3306 -h 192.168.20.11
mysql> use db_2;
mysql> create table tb_longhash (id int,name varchar(200),firstchar char(1));
#在分片2节点中创建表结构
[root@mysql-1 ~]# mysql -uroot -p123456 -P3307 -h 192.168.20.11
mysql> use db_2;
mysql> create table tb_longhash (id int,name varchar(200),firstchar char(1));
2.2.配置Mycat实现固定Hash算法分片的水平分表
2.2.1.配置Schema配置文件
[root@mysql-1 ~]# vim /data/mycat/conf/schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!--定义逻辑库 库名叫做db_shopping 该逻辑库关联dn1这个数据节点-->
<schema name="db_2" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
<!--固定Hash算法分片-->
<table name="tb_longhash" dataNode="dn1,dn2" rule="sharding-by-long-hash"/>
</schema>
<!--定义数据节点 也就是分片 一个分片会关联一个数据主机组 然后对应真实的数据库名称-->
<dataNode name="dn1" dataHost="mysqlcluster-1" database= "db_2" />
<dataNode name="dn2" dataHost="mysqlcluster-2" database= "db_2" />
<!--定义数据主机 在这个标签下定义具体的读写操作路由的数据库实例地址 schema、table划分如何指定的是该数据主机关联的数据节点 那么对应的库、表都会被存储在数据主机定义的数据库实例中-->
<dataHost name="mysqlcluster-1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<!--定义写操作路由的数据库实例-->
<writeHost host="c1-1-master3306" url="192.168.20.11:3306" user="root" password="123456">
<!--定义读操作路由的数据库实例-->
<readHost host="c1-1-slave3308" url="192.168.20.11:3308" user="root" password="123456" />
</writeHost>
<!--备用的主库 也是提供写操作的数据库,当主库c1-1-master3306故障后 备用库开始提供写操作-->
<writeHost host="c1-2-master3306" url="192.168.20.12:3306" user="root" password="123456">
<!--备用主库的从库 从始至终 只要备用主库不故障 会一直提供读服务-->
<readHost host="c1-2-slave3308" url="192.168.20.12:3308" user="root" password="123456" />
</writeHost>
</dataHost>
<dataHost name="mysqlcluster-2" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<writeHost host="c2-1-master3307" url="192.168.20.11:3307" user="root" password="123456">
<readHost host="c2-1-slave3309" url="192.168.20.11:3309" user="root" password="123456" />
</writeHost>
<!--备用主库db3 主库db1故障后 开始提供写操作-->
<writeHost host="c2-2-master3307" url="192.168.20.12:3307" user="root" password="123456">
<!--备用主库的从库 从始至终 只要备用主库不故障 会一直提供读服务-->
<readHost host="c2-2-slave3309" url="192.168.20.12:3309" user="root" password="123456" />
</writeHost>
</dataHost>
</mycat:schema>
2.2.2.配置Rule分片规则配置文件
[root@mysql-1 ~]# vim /data/mycat/conf/rule.xml
<tableRule name="sharding-by-long-hash">
<rule>
<columns>id</columns>
<!--关联固定hash的函数-->
<algorithm>sharding-by-long-hash</algorithm>
</rule>
</tableRule>
<function name="sharding-by-long-hash" class="io.mycat.route.function.PartitionByLong">
<!--定义分片节点个数 书写方式和下面的partitionLength有对应关系 例如partitionCount为1,1 partitionLength为512,512 就表示前1个分片节点承载512个数组 后1个分片节点承载512个数组-->
<property name="partitionCount">2,1</property> <!--常见的有分片数量为,书写是这么写的:2,1 表示前两个节点分别承载多少个数组,具体承载多少个数组由partitionLength定义:256,512 连起来的意思就是说前两个分片分别承载256个数组,后一个分片承载512个数组-->
<!-- 数组的总长度为1024 指定每个节点的数组数之后 多个数组相加起来必须等于1024-->
<property name="partitionLength">256,512</property>
</function>
2.2.3.配置Server配置文件
[root@mysql-1 ~]# vim /data/mycat/conf/server.xml
<user name="root" defaultAccount="true">
<!--登录用户的密码-->
<property name="password">123456</property>
<!--该用户登录后可以显示那些Schema-->
<property name="schemas">db_2</property>
</user>
2.2.4.重启Mycat
[root@mysql-1 ~]# mycat restart
Stopping Mycat-server...
Stopped Mycat-server.
Starting Mycat-server...
2.3.写入数据观察分片效果
先插入5条连续的数据。
[root@mysql-1 ~]# mysql -uroot -p123456 -P8066 -h 192.168.20.11
mysql> use db_2;
mysql> insert into tb_longhash (id,name,firstChar) values(1,'aa','Q');
mysql> insert into tb_longhash (id,name,firstChar) values(2,'nn','B');
mysql> insert into tb_longhash (id,name,firstChar) values(3,'ss','J');
mysql> insert into tb_longhash (id,name,firstChar) values(4,'ee','S');
mysql> insert into tb_longhash (id,name,firstChar) values(5,'hh','L');
可以看到数据全写入到了分片1中,这是因为1-5这个数字位运算后,还是1-5,当然会落在第一个分片中,0-511会写入到第一个分片,511-1023会写入到第二个分片。
下面我们写入的数据id值给大一些,511-1023之间,观察效果。
[root@mysql-1 ~]# mysql -uroot -p123456 -P8066 -h 192.168.20.11
mysql> use db_2;
mysql> insert into tb_longhash (id,name,firstChar) values(777,'uuu','L');
mysql> insert into tb_longhash (id,name,firstChar) values(1000,'uuu','L');
777和1000位运算后,属于512-1023之间的数据,此时会被路由到分片2中,水平分表成功。
我们再观察一种现象,如果数大于1023呢,会写入到哪里?答案是写入到第一个分片,相当于第二轮了。
[root@mysql-1 ~]# mysql -uroot -p123456 -P8066 -h 192.168.20.11
mysql> use db_2;
mysql> insert into tb_longhash (id,name,firstChar) values(1118,'uuu','L');
mysql> insert into tb_longhash (id,name,firstChar) values(1999,'uuu','L');
我们又分表插入了1118和1999这两台数据,1118属于第二轮的0-511之间的数据,路由到分片1,1999属于第二轮的512-1023的数据,路由到分片2。