MySQL集群Cluster

本文最后更新于:2023年12月5日 晚上

主从复制

主从复制用来做读写分离,主节点负责写,从节点负责读

默认异步复制,客户端性能良好,但是主从数据不一致比较常见

主从复制架构,常用的有三种:

mycat-definitive-guide.pdf

主从复制原理:

涉及到三个线程,dump 线程、io 线程、sql 线程,它们三个接力完成主从复制

dump 线程自动启动,io 线程和 sql 线程使用start slave;命令手动启动

  1. 主节点 数据更新
  2. 主节点 将数据库更改的操作写入二进制日志
  3. 主节点 的 dump 线程,将更改的二进制部分发送给从节点
  4. 从节点 的 io 线程接收主节点发过来的二进制日志,并写入到中继日志中
  5. 从节点 的 sql 线程读取中继日志,操作数据库,从而完成数据同步

relay log:中继日志,就是从主节点拷贝的二进制日志,重新命名而已,主要二进制日志不要使用 STATEMENT 模式,推荐使用 ROW 模式

实现主从复制

必要的配置项说明:

[mysqld]
# 当前节点的id号,要求全局唯一,可以使用ip的最后一位`hostname -I | awk 'BEGIN{FS="."}{print $4}'`
server-id = 1
# 开启二进制日志
log_bin = mysql-bin
# 10000次事件后master.info同步到磁盘,默认就是10000,主节点设置
sync-master-info = 10000

# 设置只读,从节点设置
read_only=ON
# relay log的文件路径,默认值hostname-relay-bin,从节点设置
relay_log=relay-log
# 默认值hostname-relay-bin.index,从节点设置
relay_log_index=relay-log.index
# 10000次写后同步relay log到磁盘,默认就是10000,从节点设置
sync_relay_log=10000
# 10000次事务后同步relay-log.info到磁盘,默认就是10000,从节点设置
sync_relay_log_info=10000

相关文件:

  • master.info:用于保存 slave 连接至 master 时的相关信息,例如账号、密码、服务器地址等
  • relay-log.info:保存在当前 slave 节点上已经复制的当前二进制日志和本地 relay log 日志的对应关系
  • mariadb-relay-bin.00000#: 中继日志,保存从主节点复制过来的二进制日志,本质就是二进制日志

启动从节点的命令:CHANGE MASTER TO

# help CHANGE MASTER TO; 查看范例
CHANGE MASTER TO
  MASTER_HOST='master2.example.com',
  MASTER_USER='replication',
  MASTER_PASSWORD='password',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='master2-bin.001',
  MASTER_LOG_POS=4,
  MASTER_CONNECT_RETRY=10;

范例:一主一从

# 主节点:10.0.0.71
# 1 如果是从零搭建,数据库是空的,如下,记住 mysql-bin.000002 和 154
(root@localhost) [(none)]> show master logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       177 |
| mysql-bin.000002 |       154 |
+------------------+-----------+
3 rows in set (0.00 sec)
# 2 创建有复制权限的用户账号
(root@localhost) [(none)]>CREATE USER 'repluser'@'10.0.0.%' IDENTIFIED BY "123456";
(root@localhost) [(none)]>GRANT replication slave ON *.* TO 'repluser'@'10.0.0.%';
(root@localhost) [(none)]>FLUSH PRIVILEGES;

# 3 使用xtrabackup全量备份数据库,将备份的数据scp到从节点,从节点还原数据

# 从节点:10.0.0.72
[root@c72 ~]$vim slave.conf
CHANGE MASTER TO
  MASTER_HOST='10.0.0.71',
  MASTER_USER='repluser',
  MASTER_PASSWORD='123456',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='mysql-bin.000002',
  MASTER_LOG_POS=154,
  MASTER_CONNECT_RETRY=10;
# 如果已经使用xtrabackup还原了数据
[root@c72 ~]$cat /data/backup/base/xtrabackup_binlog_info
mysql-bin.000002        11285
CHANGE MASTER TO
  MASTER_HOST='10.0.0.71',
  MASTER_USER='repluser',
  MASTER_PASSWORD='123456',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='mysql-bin.000002',
  MASTER_LOG_POS=11285,
  MASTER_CONNECT_RETRY=10;
# 4 启动从节点
(root@localhost) [(none)]>source ~/slave.conf
(root@localhost) [(none)]>start slave;

# 从节点清除master.info ,relay-log.info, relay log ,开始新的relay log
(root@localhost) [(none)]>stop slave;
(root@localhost) [(none)]>RESET SLAVE;

# 从节点清除master.info ,relay-log.info, relay log ,开始新的relay log,
# 并清除和主节点的同步信息,如果再和主节点同步需要重新执行CHANGE MASTER TO语句
(root@localhost) [(none)]>stop slave;
(root@localhost) [(none)]>RESET SLAVE ALL;

范例:当主节点宕机,提升一个从节点为新的主节点

# 1 找到哪个从节点的数据库是最新,让它成为新主节点
[root@centos8 ~]#cat /var/lib/mysql/relay-log.info
5
./mariadb-relay-bin.000002
1180
mysql-bin.000002
996
0
# 2 新主节点修改配置文件,关闭read-only配置
# 3 清除之前的主从复制信息
(root@localhost) [(none)]>stop slave;
(root@localhost) [(none)]>RESET SLAVE ALL;
# 4 新主节点使用xtrabackup全量备份
# 5 其他从节点重新还原数据库,指向新的主节点

实现级联复制

关键点在于中间的级联节点需要添加 log_slave_updates 配置项

# 在10.0.0.8充当master
# 在10.0.0.18充当级联slave
# 在10.0.0.28充当slave

# 在master实现
[root@centos8 ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=8
log-bin

[root@centos8 ~]#systemctl restart mariadb
[root@centos8 ~]#mysql
MariaDB [(none)]> grant replication slave on *.* to repluser@'10.0.0.%'
identified by 'magedu';
[root@centos8 ~]#mysqldump -A -F --single-transaction --master-data=1 >
/data/all.sql
[root@centos8 ~]#scp /data/all.sql 10.0.0.18:/data
[root@centos8 ~]#scp /data/all.sql 10.0.0.28:/data

# 在中间级联slave实现
[root@centos8 ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=18
log-bin
read-only
log_slave_updates #级联复制中间节点的必选项
[root@centos8 ~]#systemctl restart mariadb

# 还原数据库
[root@centos8 ~]#vim /data/all.sql
CHANGE MASTER TO
    MASTER_HOST='master节点的iP',
    MASTER_USER='repluser',
    MASTER_PASSWORD='centos',
    MASTER_PORT=3306,
    MASTER_LOG_FILE='mysql-bin.000004',
    MASTER_LOG_POS=523;

[root@centos8 ~]#mysql
MariaDB [(none)]> set sql_log_bin=0;
MariaDB [(none)]> source /data/all.sql
MariaDB [(none)]> show master logs; #记录二进制位置,给第三个节点使用
MariaDB [(none)]> set sql_log_bin=0;
MariaDB [(none)]> start slave;

# 在第三个节点slave上实现
[root@centos8 ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=28
read-only
[root@centos8 ~]#systemctl restart mariadb
[root@centos8 ~]#vim /data/all.sql
CHANGE MASTER TO
    MASTER_HOST='中间节点的IP',
    MASTER_USER='repluser',
    MASTER_PASSWORD='magedu',
    MASTER_PORT=3306,
    MASTER_LOG_FILE='mariadb-bin.000002', MASTER_LOG_POS=344;
[root@centos8 ~]#mysql < /data/all.sql
[root@centos8 ~]#mysql -e 'start slave;'

半同步复制

主从复制基于 binary log,默认情况下,客户端操作数据库,数据库修改 binary log,返回结果给客户端,然后再将 binary log 推送给从节点,这就是异步复制,客户端体验好

MySQL 还提供了另一种主从同步方式:客户端操作数据库,数据库修改 binary log,将 binary log 推送给从节点,从节点收到后马上返回 binary log(file log),然后再将 binary log 应用到数据库,主节点接收到从节点返回的信息后再返回结果给客户端,因为主节点只是确认从节点是否正确接收到 binary log,而不是等待从节点完全完成主从复制,所以这种同步叫半同步复制

半同步复制可以设置时间,超时还没有等到从节点的回复,就不等了,直接返回成功的结果给客户端

主从复制加密

默认的主从复制,传输过程是明文的,如果想加密,可以使用 SSL/TLS 加密

GTID 复制

传统的主从复制基于二进制日志,需要指定二进制日志和日志位置,从 mysql5.6 开始,支持 GTID 复制,基于 server-uuid,不需要指定二进制日志和日志位置,由主从节点自己协商同步

主从复制的监控和维护

清理日志

PURGE { BINARY | MASTER } LOGS { TO 'log_name' | BEFORE datetime_expr }
RESET MASTER TO
RESET SLAVE [ALL]

监控主从复制

SHOW MASTER STATUS
SHOW BINARY LOGS
SHOW BINLOG EVENTS
SHOW SLAVE STATUS
SHOW PROCESSLIST

从服务器是否落后于主服务

show slave status命令显示的信息中有一项数据是:Seconds_Behind_Master,它可以反映主从复制的延迟,当然实际中只靠这一个参数是不够的,其他的后面再研究

如何确定从节点数据是否一致

使用 percona-toolkit 工具,具体如何使用自行百度

数据不一致如何修复

删掉从数据库,重新复制

主从复制的问题和解决方案

数据损坏或丢失

  • 主节点:MHA + 半同步复制
  • 从节点:删掉从数据库,重新复制

不惟一的 server id

重新复制

复制延迟

  • 需要额外的监控工具的辅助
  • 一从多主:mariadb10 版后支持
  • 多线程复制:对多个数据库复制

MySQL 主从数据不一致

造成主从不一致的原因:

  • 主库 binlog 格式为 Statement,同步到从库执行后可能造成主从不一致。
  • 主库执行更改前有执行 set sql_log_bin=0,会使主库不记录 binlog,从库也无法变更这部分数据。
  • 从节点未设置只读,误操作写入数据
  • 主库或从库意外宕机,宕机可能会造成 binlog 或者 relaylog 文件出现损坏,导致主从不一致
  • 主从实例版本不一致,特别是高版本是主,低版本为从的情况下,主数据库上面支持的功能,从数据库上面可能不支持该功能
  • MySQL 自身 bug 导致

主从不一致修复方法:

  • 将从库重新实现
    虽然这也是一种解决方法,但是这个方案恢复时间比较慢,而且有时候从库也是承担一部分的查询操作的,不能贸然重建。

  • 使用 percona-toolkit 工具辅助
    PT 工具包中包含 pt-table-checksum 和 pt-table-sync 两个工具,主要用于检测主从是否一致以及修复数据不一致情况。这种方案优点是修复速度快,不需要停止主从辅助,缺点是需要知识积累,需要时间去学习,去测试,特别是在生产环境,还是要小心使用

    关于使用方法,可以参考下面链接:https://www.cnblogs.com/feiren/p/7777218.html

  • 手动重建不一致的表
    在从库发现某几张表与主库数据不一致,而这几张表数据量也比较大,手工比对数据不现实,并且重做整个库也比较慢,这个时候可以只重做这几张表来修复主从不一致这种方案缺点是在执行导入期间需要暂时停止从库复制,不过也是可以接受的
    范例:A,B,C 这三张表主从数据不一致

1、从库停止Slave复制
mysql>stop slave;

2、在主库上dump这三张表,并记录下同步的binlog和POS点
mysqldump -uroot -pmagedu -q --single-transaction --master-data=2 testdb A B C >/backup/A_B_C.sql
3、查看A_B_C.sql文件,找出记录的binlog和POS点
head A_B_C.sql
例如:MASTERLOGFILE='mysql-bin.888888', MASTERLOGPOS=666666;

#以下指令是为了保障其他表的数据不丢失,一直同步直到那个点结束,A,B,C表的数据在之前的备份已
经生成了一份快照,只需要导入进入,然后开启同步即可
4、把A_B_C.sql拷贝到Slave机器上,并做指向新位置
mysql>start slave until MASTERLOGFILE='mysql-bin.888888',
MASTERLOGPOS=666666;

5、在Slave机器上导入A_B_C.sql
mysql -uroot -pmagedu testdb
mysql>set sql_log_bin=0;
mysql>source /backup/A_B_C.sql
mysql>set sql_log_bin=1;

6、导入完毕后,从库开启同步即可。
mysql>start slave;

如何避免主从不一致:

  • 主库 binlog 采用 ROW 格式
  • 主从实例数据库版本保持一致
  • 主库做好账号权限把控,不可以执行 set sql_log_bin=0
  • 从库开启只读,不允许人为写入
  • 定期进行主从一致性检验

Galera Cluster

Galera Cluster:集成了 Galera 插件的 MySQL 集群,是一种新型的,数据不共享的,高度冗余的高可用方案,目前 Galera Cluster 有两个版本,分别是 Percona Xtradb Cluster(PXC)及 MariaDB Cluster,Galera 本身是具有多主特性的,即采用 multi-master 的集群架构,是一个既稳健,又在数据一致性、完整性及高性能方面有出色表现的高可用解决方案

Galera Cluster 特点:多主架构、同步复制、并发复制、故障切换、热拔插、自动节点克隆、对应用透明

Galera Cluster 缺点:

  • 性能由集群中最差的节点决定
  • 新节点加入后,需全量拷贝,作为 donor(贡献者)的节点在同步过程中无法提供读写
  • 只支持 innodb 存储引擎的表

Galera Cluster 工作过程:

MySQL 中间件代理服务器

数据切分

数据切分按照切分类型分为 垂直切分 和 水平切分

垂直切分是按照业务的分类将表分散到不同的库,这样也就将数据或者说压力分散到不同的库上面

优点:

  • 拆分后业务清晰,拆分规则明确
  • 系统之间整合或扩展容易
  • 数据维护简单

缺点:

  • 部分业务表无法 join,只能通过接口方式解决,提高了系统的复杂度
  • 事务处理复杂
  • 有些业务表会过于庞大,存在单库性能瓶颈

水平切分按照某个字段的某种规则,把数据切分到多张数据表。一张数据表化整为零,拆分成多张数据表

优点:

  • 拆分规则抽象好,join 操作基本可以数据库做
  • 不存在单库大数据,高并发的性能瓶颈
  • 应用端改造较少
  • 提高了系统的稳定性跟负载能力

缺点:

  • 拆分规则难以抽象
  • 分片事务一致性难以解决
  • 数据多次扩展难度跟维护量极大
  • 跨库 join 性能较差

前面讲了垂直切分跟水平切分的不同跟优缺点,会发现每种切分方式都有缺点,但共同特点缺点有:

  • 引入分布式事务的问题
  • 跨节点 Join 的问题
  • 跨节点合并排序分页问题
  • 多数据源管理问题

由于数据切分后,join 有难度,所以:

  1. 尽量不要使用 join,或者直接禁止使用 join,单独查询然后使用编程语言自行处理
  2. 可以适当增加冗余字段

注意:水平切分和垂直切分有前后顺序:先水平切分,再垂直切分:

随着数据量的增加,最先应该做的是数据分片,利用多块硬盘来增大数据 IO 能力和存储空间,这么做的成本是最低的。几块硬盘的钱就能收获不错的 IO 性能。

进入到下一个阶段,数据量继续增大,这时候我们应该把数据切分到多个 MySQL 节点上,用 MyCat 管理数据切分。当然还要做数据的读写分离等等,这里不展开讨论。在后台做水平切分的同时,业务系统也可以引入负载均衡、分布式架构等等。理论上,使用了冷热数据分离之后,水平切分这种方式可以继续维持很长一段时间,数据量再大也不怕,定期归档就好了。

数据库到了水平切分的阶段,数据量的增加已经不是更改架构设计的主要原因了。反而这个阶段业务系统承受不住了,如果再不对系统做模块拆分,业务系统也撑不下去了,所以按照模块和业务,把一个系统拆分成若干子系统。若干子系统之间,数据相对独立。比如淘宝不会跟支付支付宝分享全部数据,共享同一套数据表,这也影响各自业务的发展。所以就要弄垂直切分了,把数据表归类,拆分成若干个数据库系统。

讲到这里,你仔细想想。如果过早的对数据库做了垂直切分,势必要重新构建若干独立的业务系统,工作量太巨大。水平切分并不需要业务系统做大幅度的修改,因此说应该先从水平切分开始做。

作者:神思者
链接:http://www.imooc.com/article/288363
来源:慕课网
本文原创发布于慕课网 ,转载请注明出处,谢谢合作

MySQL 中间件

数据切分后,需要使用中间件进行数据管理

MySQL 中间件分为两类:

  • 负载均衡:Haproxy、MySQL-Proxy

  • 数据切分:MyCAT、Atlas、OneProxy、ProxySQL

    最常用的是 MyCAT 和 ProxySQL ,前者功能丰富,社区活跃,中文文档、后者性能更好,推荐使用 MyCAT

MyCAT

MyCAT 的官方文档写的很好,值得好好看一遍

ProxySQL

略…

MySQL 高可用

MHA + 半同步复制

PXC

TiDB


MySQL集群Cluster
http://blog.lujinkai.cn/运维/MySQL/MySQL集群Cluster/
作者
像方便面一样的男子
发布于
2020年12月31日
更新于
2023年12月5日
许可协议