第107讲:Mycat实践指南:取模分片下的水平分表详解

文章目录

1.使用取模分片水平分表

平台库下有一张表的数据量非常多,目前已经达到了600w行数据,查询效率很低,数据量越大,索引的结构就越高,性能会有所下降。

基于这种情况,我们决定针对这张业务表进行水平分表,分表后,原表的数据量就会被分到多张表中,缓解单表的压力,将该表的数据拆分到多个数据库实例中存放。

本次我们通过取模分片的方式来对达标进行水平分表。

取模分片指的是根据特定的字段值与分片节点数量进行求模运算,也就是除法运算取余数,根据运算结果中的余数,决定数据写入到哪一个分片中。指定取模分片的字段一定要是数字类型的字段,否则是无法进行运算的。

取模分片例子:

根据id列进行取模分片,写入数据的id为15,分片节点数为2个,运算过程:15/2=7余1,余数为1,取模分片此时就会将这个数据写入到分片2中,因为在Mycat分片中,分片的ID都是从0开始的,余数的值就是要写入对应分片节点的ID号,余数为1就对应分片2这个节点。

2.水平分表取模分片案例

在db_1数据库下有一张table1表,其数据量已经达到500w行,查询效率较低,现需要对这张表进行水平分表,采用取模分片的方法对该表进行水平分表。

2.1.准备测试的表结构

配置水平分表前,需要将要分的表在所有的分片上创建出来。

分片节点数依旧是2个,还是之前垂直分库分表时使用的两套双主双从集群。

sh 复制代码
1.在两个分片上创建数据库
[root@mysql-1 ~]# mysql -uroot -p123456 -P3306 -h 192.168.20.11 -e "create database db_2;"
[root@mysql-1 ~]# mysql -uroot -p123456 -P3307 -h 192.168.20.11 -e "create database db_2;"

2.在两个分片上创建表结构
[root@mysql-1 ~]# mysql -uroot -p123456 -P3306 -h 192.168.20.11 -e "use db_2; create table table2 (id int,name varchar(10));"
[root@mysql-1 ~]# mysql -uroot -p123456 -P3307 -h 192.168.20.11 -e "use db_2; create table table2 (id int,name varchar(10));"

2.2.配置Mycat实现范围分片的水平分表

2.2.1.配置Schema配置文件

我们针对table1这张表进行水平分表时,要为其同时指定上两个分片,然后再为其指定分片规则,同时指定两个分片后,Mycat根据分片规则路由到不同的分片上。

xml 复制代码
[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">
            <!--定义逻辑表 将table2这张大表水平拆分到dn1、dn2这两个分片上 并且分片规则使用mod-long-->
        	<table name="table2" dataNode="dn1,dn2" rule="mod-long"/>

        </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分片规则配置文件

在Rule分片规则配置文件中,我们要配置主要是根据表中的那个字段进行范围分片,如果做取模分片的字段也是id字段,就不需要调整这个配置文件,只需要调整取模分片中传入的参数。

注意:做取模分片的字段必须是数字类型的字段。

xml 复制代码
[root@mysql-1 ~]# vim /data/mycat/conf/rule.xml 
	<!--分片规则的名称-->>
    <tableRule name="mod-long">
        <rule>
            <!--基于表中那个字段进行分片-->
            <columns>id</columns>	
            <algorithm>mod-long</algorithm>
        </rule>
    </tableRule>

    <!--特定类型所对应的函数名称-->>
    <function name="mod-long" class="io.mycat.route.function.PartitionByMod">
        <!-- 分片节点数量 这个值就是取模的分母 id字段会除与这个值 得到的余数就是划分的节点ID -->
        <property name="count">2</property>
    </function>
2.2.3.配置Server配置文件
xml 复制代码
[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
sh 复制代码
[root@mysql-1 ~]# mycat restart
Stopping Mycat-server...
Stopped Mycat-server.
Starting Mycat-server...

2.3.写入数据观察水平分表效果

1)插入ID为10和15的两条数据

sql 复制代码
[root@mysql-1 ~]# mysql -uroot -p123456 -P8066 -h 192.168.20.11
mysql> use db_2;
mysql> insert into table2 (id,name) values (10,'abc');
mysql> insert into table2 (id,name) values (15,'xbz');

ID10除与分片节点数2,余数为0,那么该条数据会分配至分片1的数据库实例中。

ID15除与分片节点数1,余数为1,那么该条数据会分配至分片2的数据库实例中。

3)在Mycat中通过查询table1表就能看到所有的数据

相关推荐
alexhilton4 小时前
将应用迁移到Navigation 3:痛点、加班和紧急修复
android·kotlin·android jetpack
这个DBA有点耶8 小时前
NULL不是空——数据库里最反直觉的设计,90%新人踩过的坑
数据库·mysql·代码规范
杉氧9 小时前
Navigation Compose 深度实践:如何优雅地串联起你的全栈 App?
android·架构·android jetpack
这个DBA有点耶10 小时前
AI写的SQL跑崩了生产库,这锅谁背?
数据库·人工智能·程序员
镜舟科技11 小时前
Databricks 再提 LTAP,AI 时代的数据底座为何重回大一统叙事?
数据库·架构·agent
Databend12 小时前
从湖仓升级为 Agent 时代的数据控制面,Snowflake 和 Databricks 有哪些布局
大数据·数据库·agent
雨白13 小时前
指针与数组的核心机制
android
ClouGence15 小时前
SQL Server CDC 能放到 Always On 备库读吗?一文讲透原理与实践
数据库·sql server
花千烬16 小时前
crictl info 连不上 containerd 怎么办?endpoint、socket 与权限一次查清
云计算
黄林晴17 小时前
Room 3.0 正式发布!包名彻底重构,KMP 成为核心主线
android·android jetpack