MyCat实现MySql高可用集群
Mycat安装,基于docker
mycat安装比较简单,直接官方下载压缩包,解压即可;
myCat下载链接
mycat是java开发的,所以运行mycat需要jre支持,jre我的资源有上传,大家可以下载
为了可移植性好,我们自定义docker镜像,写个dockerfile
制作容器卷dockerfile
FROM centos
MAINTAINER dang<177372952@qq.com>
LABEL name="mycat11 myCat Image" build-data="20200901"
ADD server-jre-8u261-linux-x64.tar.gz /home/
ADD Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz /home/
ENV WORKPATH /home/mycat/
WORKDIR $WORKPATH
ENV JAVA_HOME /home/jdk1.8.0_261
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8066
CMD /home/mycat/bin/mycat console #如果需要后台启动,则改为start
Mycat启动方式
Ⅰ:bin目录
./mycat console 控制台启动(我们用这种,可以看到执行记录)
Ⅱ :bin目录
./mycat start 后台启动
构建容器命令
docker build -f myCatDockerFile -t mycat11/mycat:1.0 .
启动容器
docker run -p 8066:8066 -it 镜像ID
挂载配置文件和log至宿主机
为了方便配置和查看日志,先把容器配置文件和log复制到宿主机
docker cp 容器ID:/home/mycat/conf/ /home/docker/mycat/conf/
docker cp 容器ID:/home/mycat/logs/ /home/docker/mycat/
启动挂载容器
docker run -p 8066:8066 -it -v /home/docker/mycat/conf/:/home/mycat/conf/ -v /home/docker/mycat/logs/:/home/mycat/logs/ --net extnetwork --ip 172.20.0.4 镜像ID
docker部署mysql主从
1,下载mysql容器
docker pull mysql:5.7
2 , 先启动容器
docker run -p 3306:3306 -d -e MYSQL_ROOT_PASSWORD=123456 容器ID
3 , 进入容器
docker exec -it aeb469a58aa8 /bin/bash
4, 宿主机下home目录,新建mysql文件,用于存放配置文件和日志目录(挂载容器卷启动,不需要每次进入容器查看日志,修改配置)
5,拷贝文件到宿主机/home/mysql目录下 主从则需复制两份
docker cp 容器ID:/etc/mysql/mysql.conf.d/ /home/mysql/
docker cp 容器ID:/var/log /home/mysql/
6, 启动容器镜像
主:
docker run -p 3306:3306 --name master -d -v /home/mysql/mysql.conf.d/:/etc/mysql/mysql.conf.d/ -v /home/mysql/log/:/var/log -e MYSQL_ROOT_PASSWORD=123456 镜像ID
从:
docker run -p 3307:3306 --name slave -d -v /home/mysql2/mysql.conf.d/:/etc/mysql/mysql.conf.d/ -v /home/mysql2/log/:/var/log -e MYSQL_ROOT_PASSWORD=123456 镜像ID
docker自定义网络模式,实现容器ID固定IP
我们在使用docker容器时,每次启动容器,容器分配的虚拟IP经常变动,比如我们现在使用的mycat+mysql,我们需要配置mysql服务IP地址,这个IP是docker分配的虚拟IP,假如经常变动,我们得手动修改配置,很麻烦,所以需要固定IP
docker 默认使用的是bridge 桥接网络模式
我们可以查看 docker network ls
创建自定义网络模式
docker network create --subnet=172.20.0.0/16 extnetwork
删除自定义网络
docker network rm NETWORK ID
创建容器并指定IP
通过 --net extnetwork --ip 172.20.0.2 指定
案例:
主
docker run -p 3306:3306 --name master -d -v /home/mysql/mysql.conf.d/:/etc/mysql/mysql.conf.d/ -v /home/mysql/log/:/var/log --net extnetwork --ip 172.20.0.2 -e MYSQL_ROOT_PASSWORD=123456 镜像ID
从
docker run -p 3307:3306 --name slave -d -v /home/mysql2/mysql.conf.d/:/etc/mysql/mysql.conf.d/ -v /home/mysql2/log/:/var/log --net extnetwork --ip 172.20.0.3 -e MYSQL_ROOT_PASSWORD=123456 镜像ID
(我们启动两个mysql容器,并且固定分配IP 172.20.0.2和172.20.0.3;注意:这里必须使用172.20.0.2开始分配,因为172.20.0.1是网关)
mysql配置文件进行主从配置
现在mysql 主服务器: 172.20.0.2 从服务器: 172.20.0.3
主机配置:
打开mysqld.cnf (/home/mysql/mysql.conf.d/ 下)
添加如下配置
#主服务器ID,必须唯一
server-id=2
#开启以及设置二进制日志文件名称
log-bin=mysql-bin
#要同步的数据库
binlog-do-db=db_mycat11
#不需要同步的数据库
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
binlog-ignore-db=performation_schema
binlog-ignore-db=sys
#设置logbin格式
binlog_format=MIXED #binlog日志格式,mysql默认采用statement,建议使用mixed
从机配置
打开mysqld.cnf (/home/mysql2//mysql.conf.d/ 下)
server-id=3
relay-log=mysql-relay
配置完成后可在navicat查询
SHOW MASTER STATUS
SHOW SLAVE STATUS
主服务器创建从机访问用户以及授权,主机navicat新建查询里面运行
CREATE USER 'slave1'@'172.20.0.3' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE ON *.* TO 'slave1'@'172.20.0.3';
FLUSH PRIVILEGES;
从机创建连接主服务器的IP,用户,密码以及日志文件和位置;
CHANGE MASTER TO MASTER_HOST='172.20.0.2',MASTER_USER='slave1',MASTER_PASSWORD='123456';
MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=154;
#启动主从复制
START SLAVE;
#查看从机状态
SHOW SLAVE STATUS
从机同步数据失败 Slave_SQL_Running: No
stop slave ;
set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
start slave ;
主从复制常用命令
START SLAVE
不带任何参数,表示同时启动I/O线程和SQL线程
I/O线程从主库中读取bin log,并存储到relay log中继日志文件中
SQL线程读取中继日志,解析后,在从库重放
STOP SLAVE
完成停止I/O线程和SQL线程的操作
SHOW MASTER STATUS
查看主服务器状态
SHOW SLAVE STATUS
查看从服务器状态
RESET MASTER
删除所有的index file中记录的所有binlog文件,将日志索引文件清空,创建一个新的日志文件,这个命令通常仅仅用于第一次搭建主从关系时的主库
重置后需要删除数据库,并且从服务器重新建立连接 MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=154;(MASTER_LOG_POS在主服务查看状态position中查找)
从服务器状态
MyCat读写分离实现
读写分离介绍
基于前面的mysql主从复制,我们通过Mycat,能够实现读写分离,即master主服务器实现写操作(inster,update,delete等),slave从服务器实现读操作(select等)
主服务器一旦有写入操作,从服务器通过读取binlog,来实现数据同步,MyCat也实时发送心跳包来检测mysql服务器是否可用
读写分离核心配置详解
mycat读写分离核心配置文件schema.xml文件
schema.xml有几个标签,分别是:mycat:schema schema主配置标签,schema逻辑库配置标签,dataNode数据节点配置标签,dataHost数据库主机配置标签
一个逻辑库对应多个逻辑表,每个逻辑表如上图,可以水平分片,分成一个或多个数据分片节点,每个数据分片节点对应一个dataHost(数据库主机),dataHost里可以通过writeHost和readHost配置写主机和读主机;
schema标签属性介绍(定义逻辑数据库):
属性 | 解释 |
---|---|
name | 配置逻辑库的名字(即数据库实例名) |
checkSQLschema | SQLschema标签检查boolean类型。 当前端执行【select * from USERDB.tf_user时】(表名前指定了mycat逻辑库名),两种取值 true : mycat会把语句转为【select * from tf_user;】 false: 会报错 |
sqlMaxLimit | 最大查询每页记录数设置,相当于sql的结果集,加上【limit N】如果sql本身已经指定limit,则已sql指定为准 |
dataNode | 配置数据库节点: 用于配置该逻辑库默认的分片。没有通过table标签设置的表,就会走到默认的分片上。这里注意没有配置在table标签的表,用工具查看是无法显示的,但可以正常使用。 如果没有配置dataNode属性,则没有配置在table标签的表,是无法使用的 |
dataNode标签属性:(定义数据分片节点)
属性 | 解释 |
---|---|
name | 数据分片节点名称 |
dataHost | 定义该数据分片节点属于哪个数据库主机 |
database | 定义该数据分片节点属于哪个具体数据实例上的具体库(即对应mysql中实际的DB) |
dataHost标签属性:(定义后端的数据库主机)
属性 | 解释 |
---|---|
name | 指定dataHost的名字 |
maxCon | 指定每个读写实例连接池的最大连接。也就是说,标签内嵌套的writeHost,readHost标签都会使用这个属性的值来实例化出连接池的最大连接数 |
minCon | 指定每个读写实例连接池的最小连接,初始化连接池的大小。 |
balance | 负载均衡实例: (1)balance=“0”,不开启读写分离机制,所有读操作都发送到当前可用的writeHost上 (2)balance=“1”,全部的readHost与stand by writeHost参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡 (3)balance=“2”,所有读操作都随机在writeHost,readHost上分发 (4)balance=“3”,所有读请求随机的分发到writeHost对应的readHost执行,writeHost不负担读压力,注意balance=3只在1.4及其以后版本有,1.3没有 |
writeType | (1)writeType=“0”,所有写操作发送到配置的第一个writeHost,第一个挂了切到还生存的第二个writeHost.重新启动后已切换后的为准,切换记录在配置文件中: dnindex.properties (2)writeType=“1”,所有写操作都随机的发送到配置的writeHost,1.5以后废弃不推荐 |
dbType | 指定后端连接的数据库类型,目前支持二进制的mysql协议,还有其他使用JDBC连接的数据库,例如:mongodb,oracle,spark等 |
dbDriver | 指定连接后端数据库使用的Driver,目前可选的值有native和JDBC。使用native的话,因为这个值执行的是二进制的mysql协议,所以可以使用mysql和maridb。其他类型的数据库则需要使用JDBC驱动来支持 |
switchType | -1表示不自动切换; 1默认值,自动切换 2基于mysql主从同步的状态决定是否切换 心跳语句为show slave status 3基于mysql galary cluster 的切换机制(适合集群)(1.4.1) |
slaveThreshold | 配置真实mysql与mycat的心跳 |
heartbeat子标签属性(心跳执行SQL)
writeHost子标签属性(写主机配置)
readHost子标签属性(读主机配置)
属性 | 解释 |
---|---|
host | 用于识别不同实例,一般wiriteHost我们使用 _M1,readHost使用 _S1 |
url | 后端实例连接地址,如果是使用native的dbDriver,则一般为address:port这种形式。用JDBC或其他的dbDriver.则需要特殊指定。当使用JDBC则可以这么写:jabc:mysql://localhost:3306/. |
user | 后端存储实例需要的用户名字 |
password | 后端存储实例需要的密码 |
参考配置
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn1">
</schema>
<dataNode name="dn1" dataHost="host1" database="db_mycat11" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="172.20.0.2:3306" user="root"
password="123456">
<!-- can have multi read hosts -->
<readHost host="hostS1" url="172.20.0.3:3307" user="root" password="123456" />
</writeHost>
</dataHost>
测试mysql读写分离
修改matser主服务器配置mysqld.cnf
#设置logbin格式
binlog_format=STATEMENT #binlog日志格式,mysql默认采用STATEMENT,建议使用MIXED
重启docker master镜像
mysql读写重新配置 navicat的配置命令重新操作;如果失败,查看从机状态的错误日志 show slave status
配置完成后和在mycat数据库运行sql
INSERT into student VALUES(null,@@hostname)
查看主表@@hostname与从表hostname是否一样。不同则配置成功
MyCat搭建双主双从高可用读写分离
两对mysql主从复制搭建
主2
docker run -p 3308:3306 --name master2 -d -v /home/mysql3/mysql.conf.d/:/etc/mysql/mysql.conf.d/ -v /home/mysql3/log/:/var/log --net extnetwork --ip 172.20.0.5 -e MYSQL_ROOT_PASSWORD=123456 镜像ID
从2
docker run -p 3309:3306 --name slave2 -d -v /home/mysql4/mysql.conf.d/:/etc/mysql/mysql.conf.d/ -v /home/mysql4/log/:/var/log --net extnetwork --ip 172.20.0.6 -e MYSQL_ROOT_PASSWORD=123456 镜像ID
M1,M2我们要加配置,涉及到数据库插入id不冲突,以及数据库同步;
#在作为数据库的时候,有写入操作也要更新二进制日志文件
log-slave-updates
#表示自增长字段每次递增的量,指自增字段的起始值,其默认值是1,取值范围是1…65535
auto-increment-increment=2
#表示自增长字段从哪个数开始,指字段一次递增多少,他的取值范围是1…65535
auto-increment-offset=1
M2的 server-id=5 auto-increment-offset=2
S2的 server-id=6
配置ok后,重新搭建主从复制
M1删除user里的原先salve用户,重新授权
# ----M1和S1重新配置----#
#S1 数据库停止主从
STOP SLAVE;
#查看连接为no
SHOW SLAVE STATUS;
#M1重置master
RESET MASTER
#M1查看状态
SHOW MASTER STATUS;
#M1删除库mysql内user的用户,看下图
#M1删除之后库刷新权限
FLUSH PRIVILEGES;
#M1重新搭建用户
CREATE USER 'slave'@'172.20.0.%' IDENTIFIED BY '123456';
#M1重新授权用户
GRANT REPLICATION SLAVE ON *.* TO 'slave'@'172.20.0.%';
#M1重新刷新用户
FLUSH PRIVILEGES;
#S1配置主从配置
STOP SLAVE;
CHANGE MASTER TO MASTER_HOST='172.20.0.2',MASTER_USER='slave',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=154;
START SLAVE;
SHOW SLAVE STATUS;
# ----M1和S1重新配置----#
#M2配置
#M2重新搭建用户
CREATE USER 'slave'@'172.20.0.%' IDENTIFIED BY '123456';
#M2重新授权用户
GRANT REPLICATION SLAVE ON *.* TO 'slave'@'172.20.0.%';
#M2重新刷新用户
FLUSH PRIVILEGES;
#M2数据库user表内新增slave用户,可查看
#S2配置
STOP SLAVE;
CHANGE MASTER TO MASTER_HOST='172.20.0.5',MASTER_USER='slave',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=617;
START SLAVE;
SHOW SLAVE STATUS;
M1和M2配置互为主从复制搭建
#M2创建复制
#M2复制M1
CHANGE MASTER TO MASTER_HOST='172.20.0.2',MASTER_USER='slave',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=154;
START SLAVE;
SHOW SLAVE STATUS;
#M1复制M2
CHANGE MASTER TO MASTER_HOST='172.20.0.5',MASTER_USER='slave',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=154;
START SLAVE;
SHOW SLAVE STATUS;
MyCat双主双从读写分离实现
修改schema.xml配置文件
<dataNode name="dn1" dataHost="host1" database="db_mycat11" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="172.20.0.2:3306" user="root"
password="123456">
<!-- can have multi read hosts -->
<readHost host="hostS1" url="172.20.0.3:3306" user="root" password="123456" />
</writeHost>
<writeHost host="hostM2" url="172.20.0.5:3306" user="root"
password="123456">
<!-- can have multi read hosts -->
<readHost host="hostS2" url="172.20.0.6:3306" user="root" password="123456" />
</writeHost>
</dataHost>
#balance改为1 现在是双主双从
#balance=‘1’,全部的readHost与stand by writeHost参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡
MyCat双主双从读写分离测试
#mycat执行sql
insert into student values(null,@@hostname)
#执行会发现M1,S1,S2都有数据,不断刷新数据,会发现从S1,M2,S2随机读取,可以判断M1是作为写主机的
MyCat垂直分库最佳实践
mycat官方说明了,支持单库内任意join,所以我们设计的时候,把同一个业务模块的表放同一个库,依据业务模块来垂直分库;
所以我们最终分库原则以下三点:
1,根据业务模块来划分,不搞跨库join操作,避坑
2,公共表,比如数据字典表,系统属性等,采用全局表
3,有些核心表,比如用户表,部门表,权限表等,业务模块偶尔用到的时候,可以通过API方式查询,无需划分到具体业务模块里去
垂直分库案例实现
抽象电商系统四个表:用户表,商品表,订单表,数据字典表
用户表
CREATE TABLE ‘t_user’(
‘id’ int(11) NOT NULL AUTO_INCREMENT COMMENT ‘编号’,
‘userName’ varchar(20) DEFAULT NULL COMMENT ‘用户名’,
‘password’ varchar(20) DEFAULT NULL COMMENT ‘密码’,
PRIMARY KEY (‘id’)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
商品表
CREATE TABLE ‘t_product’(
‘id’ int(11) NOT NULL AUTO_INCREMENT COMMENT ‘编号’,
‘name’ varchar(50) DEFAULT NULL COMMENT ‘商品名称’,
‘price’ decimal(10,0) DEFAULT NULL COMMENT ‘价格’,
‘description’ text COMMENT ‘描述’,
‘stock’ int(11) DEFAULT NULL COMMENT ‘库存量’,
PRIMARY KEY (‘id’)
)ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
订单表
CREATE TABLE ‘t_order’(
‘id’ int(11) NOT NULL AUTO_INCREMENT COMMENT ‘编号’,
‘pId’ int(11) DEFAULT NULL COMMENT ‘商品编号’,
‘num’ int(11) DEFAULT NULL COMMENT ‘购买数量’,
‘uId’ int(11) DEFAULT NULL COMMENT ‘用户编号’,
‘orderDate’ datetime DEFAULT NULL COMMENT ‘下单时间’,
PRIMARY KEY (‘id’)
)ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
数据字典表
CREATE TABLE ‘t_datadic’(
‘id’ int(11) NOT NULL AUTO_INCREMENT COMMENT ‘编号’,
‘name’ varchar(50) DEFAULT NULL COMMENT ‘数据字典名称’,
‘value’ varchar(20) DEFAULT NULL COMMENT 数据字典值’,
‘remark’ varchar(100) DEFAULT NULL COMMENT ‘备注’,
PRIMARY KEY (‘id’)
)ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
insert into ‘t_datadic’(‘id’,‘name’,‘value’,‘remark’) values (1,‘性别’,‘男’,null),(2,‘性别’,‘女’,null),(3,‘性别’,‘男变女’,null),(4,‘性别’,‘女变男’,null),(5,‘政治面貌’,‘共产党’,null),(6,‘政治面貌’,‘共青团员’,null),(7,‘政治面貌’,‘无党派人士’,null);
数据字典作为全局表以后再说
我们分两个库 t_user一个库,t_product和t_order一个库,因为有join关联
t_user放db_mall_user库
t_product和t_order放db_mall_order库
编号 | 角色 | 分配ID |
---|---|---|
1 | db_mall_user库 | 172.20.0.7 |
2 | db_mall_order库 | 172.20.0.8 |
mycat | 172.20.0.9 |
启动两个mysql
docker run -p 3306:3306 --name db_mall_user -d -v /home/mysql7/mysql.conf.d/:/etc/mysql/mysql.conf.d/ -v /home/mysql37/log/:/var/log --net extnetwork --ip 172.20.0.7 -e MYSQL_ROOT_PASSWORD=123456 镜像ID
docker run -p 3307:3306 --name db_mall_order -d -v /home/mysql8/mysql.conf.d/:/etc/mysql/mysql.conf.d/ -v /home/mysql8/log/:/var/log --net extnetwork --ip 172.20.0.8 -e MYSQL_ROOT_PASSWORD=123456 镜像ID
创建数据库 db_mall_user 和 db_mall_order
配置schemal.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100">
<table name="t_user" primaryKey="id" dataNode="dn1" />
<table name="t_order" primaryKey="id" dataNode="dn2" />
<table name="t_product" primaryKey="id" dataNode="dn2" />
</schema>
<dataNode name="dn1" dataHost="host1" database="db_mall_user" />
<dataNode name="dn2" dataHost="host2" database="db_mall_order" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="172.20.0.7:3306" user="root"
password="123456">
</writeHost>
</dataHost>
<dataHost name="host2" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM2" url="172.20.0.8:3306" user="root"
password="123456">
</writeHost>
</dataHost>
</mycat:schema>
启动mycat
docker run -p 8066:8066 -it -v /home/docker/mycat1/conf/:/home/mycat/conf/ -v /home/docker/mycat1/logs/:/home/mycat/logs/ --net extnetwork --ip 172.20.0.9 镜像ID
启动成功后通过mycat建库实现垂直分库
垂直分库优缺点
优点:1,拆分简单明了,拆分规则明确
2,应用程序模块清晰明确,整合容易
3,数据维护方便易行,容易定位
4,减轻了单个库的负载
缺点:1,部分表关联无法在数据库级别完成,需要在程序中完成
2,对于访问机器频繁且数据量超大的表依然存在性能瓶颈
3,切分达到一定程度后,扩展性会遇到限制,单表性能依然存在瓶颈
MyCat水平分表
水平分表原则:具体怎么个水平分表法,我们最终是要根据具体业务把单表的请求负载均衡分散到多库中。
不能出现大量的请求集中到1,2个分表
比如订单表,我们划分的时候,不能根据id来划分,因为平时查询的时候是根据某个用户id去查询用户的订单信息
所以我们订单表的划分原则是根据用户id取模划分,这样的话,请求能均衡的分布到多个分表,以及查询的时候大部分情况都是一个分表查询,效率会高一点
Mycat常用的分片规则如下:
1,分片枚举:sharding-by-intfile
2,主键范围约定:auto-sharding-long 此分片适用于,提前规划好分片字段某个范围属于哪个分片
3,一致性hash:sharding-by-murmur
4,字符串hash解析:sharding-by-stringhash
5,按日期(天)分片:sharding-by-date
6,按单月小时拆分:sharding-by-hour
7,自然月分片:sharding-by-month
8,取模:mod-long 此规则为对分片字段求模运算
9,取模范围约束:sharding-by-pattern 此种规则是取模运算与范围约束的结合,主要为了后续数据迁移作准备,即可以自主决定取模后数据的节点分布
水平分表取模分片实现
配置mycat schema.xml
两个分片节点 dn2,dn3
name=“t_order” primaryKey=“id” dataNode=“dn2,dn3” rule = "order-rule"
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100">
<table name="t_user" primaryKey="id" dataNode="dn1" />
<table name="t_order" primaryKey="id" dataNode="dn2,dn3" rule = "order-rule" />
</schema>
<dataNode name="dn1" dataHost="host1" database="db_mall_user" />
<dataNode name="dn2" dataHost="host2" database="db_mall_order" />
<dataNode name="dn3" dataHost="host3" database="db_mall_order" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="172.20.0.7:3306" user="root"
password="123456">
</writeHost>
</dataHost>
<dataHost name="host2" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM2" url="172.20.0.8:3306" user="root"
password="123456">
</writeHost>
</dataHost>
<dataHost name="host3" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM3" url="172.20.0.9:3306" user="root"
password="123456">
</writeHost>
</dataHost>
</mycat:schema>
自定义规则 rule.xml
添加规则
<tableRule name="order-rule">
<rule>
#根据用户ID定义规则
<columns>uId</columns>
#规则方法 取模
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
因为只有两个分片节点,所以修改mod-long的count为2
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<!-- how many data nodes -->
<property name="count">2</property>
</function>
分库分表,启动三个mysql
docker run -p 3306:3306 --name db_mall_user -d -v /home/mysql7/mysql.conf.d/:/etc/mysql/mysql.conf.d/ -v /home/mysql37/log/:/var/log --net extnetwork --ip 172.20.0.7 -e MYSQL_ROOT_PASSWORD=123456 镜像ID
docker run -p 3307:3306 --name db_mall_order -d -v /home/mysql8/mysql.conf.d/:/etc/mysql/mysql.conf.d/ -v /home/mysql8/log/:/var/log --net extnetwork --ip 172.20.0.8 -e MYSQL_ROOT_PASSWORD=123456 镜像ID
docker run -p 3308:3306 --name db_mall_order2 -d -v /home/mysql9/mysql.conf.d/:/etc/mysql/mysql.conf.d/ -v /home/mysql9/log/:/var/log --net extnetwork --ip 172.20.0.9 -e MYSQL_ROOT_PASSWORD=123456 镜像ID
启动mycat
docker run -p 8066:8066 -it -v /home/docker/mycat2/conf/:/home/mycat/conf/ -v /home/docker/mycat2/logs/:/home/mycat/logs/ --net extnetwork --ip 172.20.0.6 镜像ID
测试,创建数据库 db_mall_user db_mall_order
创建表 t_user t_order order里面包含uId字段
通过mycat插入数据通过uId取模分别入两个库的 t_order 表
水平分表全局自增ID
使用mycat支持生成的全局自增ID
1,mycat配置文件conf中找到dbseq.sql 复制粘贴到dn2(分片表中的一个)运行;数据库会多出一张MYCAT_SEQUENCE表,且会生成四个函数
2,编辑配置文件 sequence_db_conf.properties文件添加到conf中
GLOBAL=dn2
COMPANY=dn2
CUSTOMER=dn2
ORDERS=dn2
3,修改server.xml配置文件的sequnceHandlerType配置,改为1
sequnceHandlerType配置
0 本地方式
1 数据库方式
2 时间戳方式
<property name="sequnceHandlerType">1</property>
4,重启mycat
删除原本数据
添加sql语句,注意id添加为 ‘next value for MYCATSEQ_GLOBAL’,uId为取模分片id
INSERT INTO T_ORDER(id,pId,num,uId,orderDate) VALUES ('next value for MYCATSEQ_GLOBAL',1,1,4,NULL);
全局表配置
mycat修改配置文件schema.xml T_DATADOC为全局表名称
新加配置
<table name="T_DATADOC" primaryKey="id" dataNode="dn1,dn2,dn3" rule = "global" />
重启mycat