1.字符串Hash算法分片的概念

1.1.字符串Hash算法的概念

字符串Hash算法指的是,从依据字段的内容中,截取字符串中指定位置的子字符串,然后将这个子字符串进行Hash运算,得到一个二进制数字,然后再拿这个二进制数字与1023也就是1111111111进行位运算,最后计算出该条数据应该落在哪个分片上。

字符串Hash算法与固定Hash算法类似,只不过固定Hash算法不能针对字符串处理,而字符串Hash算法可以将字符串转换成二进制数,然后再通过固定Hash算法计算出数据要落在哪个分片上。

第112讲:Mycat实践指南:字符串Hash算法分片下的水平分表详解-LMLPHP

1.2.字符串Hash算法是如何将数据路由到分片节点的

字符串Hash算法其实就是将字段值为字符串的内容,转换成二进制数,然后通过固定Hash计算出应该落在哪个节点上。

我们会在定义分片策略时,一共有2个分片节点,例如定义第一个节点存储位运算结果0-511之间的数据,第二个节点处理512-1023之间的数据,此时每个分片节点都处理512个数组,是均匀分配的现象。

在0-511之间数组的结构中,会记录上第一个分片节点的ID0,512-1023之间的数组的结构中,记录第二个分片节点的ID1。

当字段值为word时,首先根据截取的子字符串长度(0:2)截取3位,截取后子字符串为wor,然后通过Hash运算得到一个二进制数,再通过固定Hash,将二进制数与1111111111进行位运算,得到一个十进制数5,拿着这个十进制数5在数组集合中查找,最后查找到5位于0-511之内,0-511属于分片1,此时这条数据就会路由到分片1中存储。

第112讲:Mycat实践指南:字符串Hash算法分片下的水平分表详解-LMLPHP

2.使用字符串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_strhash (name varchar(20),content varchar(100));


#在分片2节点中创建表结构
[root@mysql-1 ~]# mysql -uroot -p123456 -P3307 -h 192.168.20.11
mysql> use db_2;
mysql> create table tb_strhash (name varchar(20),content varchar(100));

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_strhash" dataNode="dn1,dn2" rule="sharding-by-stringhash" />
        </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-stringhash"> 
        <rule>
            <columns>name</columns>
            <algorithm>sharding-by-stringhash</algorithm> 
        </rule>
    </tableRule>
    
    <function name="sharding-by-stringhash" class="io.mycat.route.function.PartitionByString">
        <!--每个分片所承载的数组数量-->
        <property name="partitionLength">512</property> 
        <!--分片节点的数量-->
        <property name="partitionCount">2</property>
        <!--字符串的截取长度,0:2表示截取第0/1/2位,一共3位长度的子字符串-->
        <property name="hashSlice">0:2</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.写入数据观察分片效果

[root@mysql-1 ~]# mysql -uroot -p123456 -P8066 -h 192.168.20.11
mysql> use db_2;
mysql> insert into tb_strhash (name,content) values ('T1001', UUID());
mysql> insert into tb_strhash (name,content) values ('ROSE', UUID());
mysql> insert into tb_strhash (name,content) values ('JERRY', UUID());
mysql> insert into tb_strhash (name,content) values ('CRISTINA', UUID());
mysql> insert into tb_strhash (name,content) values ('TOMCAT', UUID());

可以看到一部分数据写入到了分片1中,一部分数据写入到了分片2中。

第112讲:Mycat实践指南:字符串Hash算法分片下的水平分表详解-LMLPHP

03-24 23:10