通过上一篇幅讲解,应该很清楚分片规则配置文件rule.xml
位于$MYCAT_HOME/conf目录,它定义了全部拆分表的规则。在使用过程当中能够灵活使用不一样的分片算法,或者对同一个分片算法使用不一样的参数,它让分片过程可配置化,只须要简单的几步就可让运维人员及数据库管理员轻松将数据拆分到不一样的物理库中。该文件包含两个重要的标签,分别是Funcation和tableRule。java
整体上分为连续分片和离散分片,还有一种是连续分片和离散分片的结合,例如先范围后取模。好比范围分片(id 或者时间)就是典型的连续分片,单个分区的数量和边界是肯定的。离散分片的分区总数量和边界是肯定的,例如对 key 进行哈希运算,或者再取模。mysql
关于连续分片在上一篇幅中已经讲过,那么在这一篇幅中就不演示了,在这里主要写下怎么配置及他的特色:算法
特色:容易出现冷热数据sql
其实这里面的按月分配和上一篇幅中讲的单表中按月分片是同样的形式,惟一的区别就是一个是单库一个是多库;docker
在上一篇幅中的三个ghymycat库中接着建立三张表数据库
-- 建立表 CREATE TABLE `month` ( `create_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, `name` varchar(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
在schema.xml中加入逻辑表vim
在rule.xml中加入分片规则bash
事情搞定那和上一篇幅同样,启动mycat服务而后测试 服务器
INSERT INTO month (create_time,name) VALUES ('2024-10-16', '11'); INSERT INTO month (create_time,name) VALUES ('2025-10-27', '11'); INSERT INTO month (create_time,name) VALUES ('2026-11-04', '11'); INSERT INTO month (create_time,name) VALUES ('2027-11-11', '11'); INSERT INTO month (create_time,name) VALUES ('2029-12-25', '11'); INSERT INTO month (create_time,name) VALUES ('2030-12-31', '11');
根据分片键进行十进制求模运算。student表前面已经有讲过架构
特色:在插入数据时他会均匀的分布在全部节点上,解决了上面的冷热数据问题,可是他在数据迁移和增删节点时工做量会比较大
枚举分片适用场景,列值的个数是固定的,譬如省份,月份等。例如:全国 34 个省,要将不一样的省的数据存放在不一样的节点,可用枚举的方式。
和前面样,在三个ghymycat库中建立表
CREATE TABLE `t_vote` ( `age` int(11) NOT NULL, `name` varchar(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
而后创建逻辑表
创建分片规则
最后创建分片算法
策略文件
测试数据
INSERT INTO `sharding_by_intfile` (age,name) VALUES (16, 11); INSERT INTO `sharding_by_intfile` (age,name) VALUES (17, 11); INSERT INTO `sharding_by_intfile` (age,name) VALUES (18, 11);
特色:如开头说的同样适用于枚举值固定的场景。
一致性 hash 有效解决了分布式数据的扩容问题。
原理:为将数据均匀分布在各个节点中。对其进行哈希,取值在 0 ~ 232-1 闭环中定位到顺时针第一个节点,将此数据分配其中。因为节点有限,可能取哈希分布不均。设置虚拟节点好比160,先将哈希分布在160节点上,而后把对应的节点聚合到真实节点中。
在三个数据库ghymycat中建表
CREATE TABLE `consistency` ( `id` int(10) DEFAULT NULL, `name` varchar(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
逻辑表
分片规则
分片算法
INSERT INTO `consistency` (id,name) VALUES (1, '张三'); INSERT INTO `consistency` (id,name) VALUES (2, '张三'); INSERT INTO `consistency` (id,name) VALUES (3, '张三'); INSERT INTO `consistency` (id,name) VALUES (4, '张三'); INSERT INTO `consistency` (id,name) VALUES (5, '张三'); INSERT INTO `consistency` (id,name) VALUES (6, '张三'); INSERT INTO `consistency` (id,name) VALUES (7, '张三'); INSERT INTO `consistency` (id,name) VALUES (8, '张三'); INSERT INTO `consistency` (id,name) VALUES (9, '张三'); INSERT INTO `consistency` (id,name) VALUES (10, '张三'); INSERT INTO `consistency` (id,name) VALUES (11, '张三'); INSERT INTO `consistency` (id,name) VALUES (12, '张三'); INSERT INTO `consistency` (id,name) VALUES (13, '张三'); INSERT INTO `consistency` (id,name) VALUES (14, '张三'); INSERT INTO `consistency` (id,name) VALUES (15, '张三'); INSERT INTO `consistency` (id,name) VALUES (16, '张三'); INSERT INTO `consistency` (id,name) VALUES (17, '张三'); INSERT INTO `consistency` (id,name) VALUES (18, '张三'); INSERT INTO `consistency` (id,name) VALUES (19, '张三'); INSERT INTO `consistency` (id,name) VALUES (20, '张三');
特色:能够必定程度减小数据的迁移能够解决容灾,扩容。例如真实节点3个,好比:a,b,c;b宕机,原来要分配到b节点上的会分配到c上;加节点x到ac中间,原来分配到c节点的数据分配到x节点上。
这是先求模获得逻辑分片号,再根据逻辑分片号直接映射到物理分片的一种散列算法。
同样在三个ghymycat中建立表
CREATE TABLE `immobilization` ( `id` int(10) DEFAULT NULL, `name` varchar(20) DEFAULT NULL ) ;
逻辑表
分片规则
平均分红 8 片(%1024 的余数,1024=128*8):
这是均匀分布的例子,下面再配置一个不均匀分布的例子,只用 改动分片算法(%1024 的余数,1024=2*256+1*512)
INSERT INTO `immobilization` (id,name) VALUES (222, '张三'); INSERT INTO `immobilization` (id,name) VALUES (333, '张三'); INSERT INTO `immobilization` (id,name) VALUES (666, '张三');
先进行取模运算再根据求余结果范围进行分片,该种分片规则首先根据配置的分片字段,与配置的取模基数进行求余操做,根据求余的结果,而后判断在哪个分片范围内,由此对应到具体某个数据分片上。
建表数据
CREATE TABLE `delivery` ( `id` varchar(20) DEFAULT NULL, `name` varchar(20) DEFAULT NULL ) ;
逻辑表
分片规则
分片算法
INSERT INTO `delivery` (id,name) VALUES (19, '张三'); INSERT INTO `delivery` (id,name) VALUES (222, '张三'); INSERT INTO `delivery` (id,name) VALUES (371, '张三');
该算法先进行范围分片,计算出分片组,组内在取模
CREATE TABLE `delivery_mod` ( `id` varchar(20) DEFAULT NULL, `name` varchar(20) DEFAULT NULL ) ;
逻辑表
分片规则
分片算法
INSERT INTO `delivery_mod` (id,name) VALUES (666, '张三'); INSERT INTO `delivery_mod` (id,name) VALUES (6667, '张三'); INSERT INTO `delivery_mod` (id,name) VALUES (16666, '张三'); INSERT INTO `delivery_mod` (id,name) VALUES (21111, '张三'); INSERT INTO `delivery_mod` (id,name) VALUES (22222, '张三');
1.2.六、其余分片规则
连续分片优势:
连续分片缺点:
离散分片优势:
离散分片缺点:
1、准备工做
2、扩容缩容步骤
下面以取模分片表student为例
复制 schema.xml、rule.xml 并重命名为 newSchema.xml、newRule.xml 放于 conf 目录下
修改 newSchema.xml 和 newRule.xml 配置文件为扩容缩容后的 mycat 配置参数(表的节点数、数据源、路由规则)注意:只有节点变化的表才会进行迁移。仅分片配置变化不会迁移。
修改newSchema.xml配置
由于节点数发生了变化因此newRule.xml配置中的count节点数也须要修改为2
修改 conf 目录下的 migrateTables.properties 配置文件,告诉工具哪些表须要进行扩容或缩容,没有出如今此配置文件的 schema 表不会进行数据迁移,格式:
注意:
修改bin目录下的dataMigrate.sh脚本文件,参数以下:
tempFileDir 临时文件路径,目录不存在将自动建立 isAwaysUseMaster默认true:不管是否发生主备切换,都使用主数据源数据,false:使用当前数据源 mysqlBin:mysql bin路径 cmdLength mysqldump命令行长度限制 默认110k 110*1024。在LINUX操做系统有限制单条命令行的长度是128KB,也就是131072字节,这个值可能不一样操做系统不一样内核都不同,若是执行迁移时报Cannot run program "sh": error=7, Argument list too long 说明这个值设置大了,须要调小此值。 charset导入导出数据所用字符集 默认utf8 deleteTempFileDir完成扩容缩容后是否删除临时文件 默认为true threadCount并行线程数(涉及生成中间文件和导入导出数据)默认为迁移程序所在主机环境的cpu核数*2 delThreadCount每一个数据库主机上清理冗余数据的并发线程数,默认为当前脚本程序所在主机cpu核数/2 queryPageSize 读取迁移节点所有数据时一次加载的数据量 默认10w条
指定临时文件路径 #临时文件路径,目录不存在将自动建立,不指定此目录则默认为mycat根下的temp目录 RUN_CMD="$RUN_CMD -tempFileDir=/root/data/program/mycat/temp" 指定为false能够查看此过程当中产生的sql #完成扩容缩容后是否删除临时文件 默认为true RUN_CMD="$RUN_CMD -deleteTempFileDir=false"
经过命令"find / -name mysqldump"查找mysqldump路径为"/usr/bin/mysqldump",指定#mysql bin路径为"/usr/bin/"
#mysql bin路径 RUN_CMD="$RUN_CMD -mysqlBin=/usr/bin/" 这个必定得配置
中止mycat服务(若是能够确保扩容缩容过程当中不会有写操做,也能够不中止mycat服务)
经过crt等工具进入mycat根目录,执行bin/ dataMigrate.sh脚本,开始扩容/缩容过程:
脚本执行完成,若是最后的数据迁移验证经过,就能够将以前的 newSchema.xml和 newRule.xml 替换以前的 schema.xml 和 rule.xml 文件,并重启 mycat 便可。
注意事项:
前面已经用 mycat 实现了 MySQL 数据的分片存储,第一个能够实现负载均衡,不一样的读写发生在不一样的节点上。第二能够实现横向扩展,若是数据持续增长,加机器就 能够了。固然,一个分片只有一台机器还不够。为了防止节点宕机或者节点损坏,都要用副本机制来实现。MySQL 数据库一样能够集群部署,有了多个节点以后,节点之间数据又是个大问题。因此下面说下实现节点数据同步
3、MySQL 主从复制
主从同步原理:
准备两台机器
master 192.168.2.103
slave 192.168.2.106
由于我是在docker中建的mysql容器,因此想要进入mysql内部要执行下面命令
docker exec -it e1066fe2db35 /bin/bash
若是没装vim的要先装下vim,运行命令:apt-get install vim
这时候须要运行命令:apt-get update
这个命令的做用是:同步 /etc/apt/sources.list 和 /etc/apt/sources.list.d 中列出的源的索引,这样才能获取到最新的软件包。
从新运行命令:apt-get install vim
安装完成。
若是用clone的方式获得两个MySQL服务,须要注意的地方:不一样机器的UUID不能重复,不然IO线程不能启动:
find / -name auto.cnf vim /var/lib/mysql/auto.cnf
把里面的UUID随便改掉一位。
重启服务命令:
service mysqld restart
vim /etc/mysql/my.cnf文件
[mysqld]下面增长几行配置:
log-bin=mysql-bin binlog-format=ROW server_id=1
配置完成以后,须要重启mysql服务使配置生效。使用service mysql restart完成重启。
在103主节点建立给slave 106节点访问的用户(发放通行证)
链接到MySQL:
mysql -uroot -proot;
执行SQL:
CREATE USER 'repl'@'192.168.2.106' IDENTIFIED BY 'root'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.2.106'; FLUSH PRIVILEGES;
若是有多个slave节点,使用同一个用户,也能够把IP设置成通配符的方式,例如192.168.2.*
接下来要获取最新的binlog文件名和position
show master status;
记住file名字和position,后面会用到。这个时候master不要发生写操做,不然position和file可能会变化。
[mysqld]下面增长几行配置:
log-bin=mysql-slave-bin binlog-format=ROW server_id=2
配置完成以后,须要重启mysql服务使配置生效。使用service mysql restart完成重启。
链接到MySQL:
mysql -uroot -proot;
file和pos是从主节点获取的
change master to master_host='192.168.2.103', master_user='repl', master_password='root', master_log_file='mysql-bin.000028', master_log_pos=773;
show slave status;
注意,主从同步成功的标志:
IO线程和SQL线程都是成功运行的:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
如今能够在master节点上面作任意对于库表的修改操做,slave会自动同步。
不要直接操做slave。
若是IO线程not running:
stop slave; SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; start slave; show slave status\G
在 MySQL 多服务器的架构中,主节点,也就是产生数据的节点叫 master 节点。其他的副本,向主节点同步数据的节点,叫作 slave(默认是异步的,客户端的数据在 master刷盘就返回)。一个集群里面至少要有一个 master。slave 能够有多个。
数据备份:把数据复制到不一样的机器上,以避免单台服务器发生故障时数据丢失。负载均衡:结合负载的机制,均摊全部的应用访问请求,下降单机 IO。高可用 HA:当节点故障时,自动转移到其余节点,提升可用性。主从复制的架构能够有多种
不过在,MySQL 自身并无自动选举和故障转移的功能,须要依赖其余的中间件或者架构实现,好比 MMM,MHA,percona,mycat。下面就来讲下主从的实现
客户端对 MySQL 数据库进行操做的时候,包括 DDL 和 DML 语句,服务端会在日志文件中用事件的形式记录全部的操做记录,这个文件就是 binlog 文件(属于逻辑日志,跟 Redis 的 AOF 文件相似)。Binary log,二进制日志。基于 binlog,咱们能够实现主从复制和数据恢复。binlog 默认是不开启的,须要在服务端手动配置。注意有必定的性能损耗。
编辑 /etc/my.cnf
log-bin=mysql-bin server-id=1
重启 MySQL 服务
service mysqld stop service mysqld start ##若是出错查看日志
vi /var/log/mysqld.log
cd /var/lib/mysql
是否开启 binlog
show variables like 'log_bin%';
STATEMENT:记录每一条修改数据的 SQL 语句(减小日志量,节约 IO)。
ROW:记录哪条数据被修改了,修改为什么样子了(5.7 之后默认)。
MIXED:结合两种方式,通常的语句用 STATEMENT,函数之类的用
ROW。查看 binlog 格式:
show global variables like '%binlog_format%';
Binlog 文件超过必定大小就会产生一个新的,查看 binlog 列表:
show binary logs;
大小:
show variables like 'max_binlog_size';
查看 binlog 内容
show binlog events in 'mysql-bin.000001';
用 mysqlbinlog 工具,基于时间查看 binlog
/usr/bin/mysqlbinlog --start-datetime='2025-08-22 13:30:00' --stop-datetime='2025-08-22 14:01:01' -d ljxmycat /var/lib/mysql/mysql-bin.000001
一、主库开启 binlog,设置 server-id
二、在主库建立具备复制权限的用户,容许从库链接
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'@'192.168.2.106' IDENTIFIED BY 'root'; FLUSH PRIVILEGES;
三、从库/etc/my.cnf 配置,重启数据库
server-id=2 log-bin=mysql-bin relay-log=mysql-relay-bin read-only=1 log-slave-updates=1
开启 log-slave-updates 参数后,从库从主库复制的数据会写入 log-bin 日志文件里,这样能够实现互为主备或者级联复制(它本身也能够做为一个 master 节点)。
四、在从库执行
stop slave; change master to master_host='192.168.2.103',master_user='repl',master_password='root',master_log_file='mysql-bin.00000 1', master_log_pos=4; start slave;
五、查看同步状态
SHOW SLAVE STATUS
Slave_IO_Running 和 Slave SQL Running 都为 yes 为正常。
一、slave 服务器执行 start slave,开启主从复制开关, slave 服务器的 IO 线程请求从 master 服务器读取 binlog(若是该线程追遇上了主库,会进入睡眠状态)。
二、master 服务器建立 Log Dump 线程,把 binlog 发送给 slave 服务器。slave 服务器把读取到的 binlog 日志内容写入中继日志 relay log(会记录位置信息,以便下次继续读取)。
三、slave 服务器的 SQL 线程会实时检测 relay log 中新增的日志内容,把 relay log 解析成 SQL 语句,并执行。
为何须要 relay log?为何不把接收到的 binlog 数据直接写入从库? Relay log 至关于一个中转站,也记录了 master 和 slave 的同步信息。
<dataHost name="host122" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <writeHost host="hostM1" url="192.168.2.103:3306" user="root" password="root"> <readHost host="hostS1" url="192.168.2.104:3306" user="root" password="root" /> </writeHost> </dataHost>
balance:负载的配置,决定 select 语句的负载
writeType:读写分离的配置,决定 update、delete、insert 语句的负载
switchType:主从切换配置