告别单点故障!MySQL Group Replication如何重塑金融级数据库架构
MySQL Group Replication(组复制)是 MySQL 提供的一种高级高可用解决方案,基于 Paxos 协议实现多主复制,适合对数据一致性和高可用性要求高的场景。
一、技术原理
1.1架构设计原理
1.1.1 多主复制机制
- Paxos共识算法:
通过分布式投票机制保证事务提交的原子性,集群中超过半数节点确认即视为提交成功 - 数据流向模型:
https://via.placeholder.com/600x300?text=Multi-Master+Replication+Flow
- 本地事务处理:各节点独立执行SQL
- 全局事务协调:通过Group Communication Framework(GCF)广播事务事件
- 冲突解决方案:基于
transaction_write_set_extraction
算法检测冲突,采用版本向量(Version Vectors)解决写入冲突
1.1.2 故障转移机制
- 智能心跳检测:
每3秒发送Gossip消息,节点失联超过group_replication_unavailable_timeout
(默认30秒)触发故障判定 - 自动选举算法:
基于Raft协议的领导者选举,新主节点从候选节点中选择GROUP_REPLICATION_ADMIN
角色持有者
1.2. 适用场景
- 高可用需求:需要自动故障转移和多主复制能力。
- 数据一致性要求高:如金融、支付等关键业务场景。
- 多写场景:需要多个节点同时处理写请求。
二.部署组复制
2.1. 服务器信息
主机 |
IP 地址 |
操作系统 |
角色 |
master |
192.168.3.28 |
Ubuntu 22.04 |
主节点 |
node1 |
192.168.3.29 |
Ubuntu 22.04 |
从节点 |
node2 |
192.168.3.30 |
Ubuntu 22.04 |
从节点 |
2.2. 配置 my.cnf
在三台主机上创建 MySQL 容器并映射目录:
sudo mkdir -p /opt/mysql/data /opt/mysql/conf /opt/mysql/files
在三台主机上配置 /opt/mysql/conf/my.cnf
,确保每个主机的 server-id
不同:
[mysqld]
# 设置服务器ID,确保在复制环境中每个MySQL实例的ID是唯一的
server-id = 1
# 指定MySQL服务监听的端口号
port = 3309
# 禁用指定的存储引擎,防止使用这些可能不适合当前应用场景的存储引擎
disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
# 设置默认时区为东八区(北京时间)
default_time_zone = "+8:00"
# 设置事务隔离级别为读已提交,适合大多数需要避免脏读的应用场景
transaction_isolation = READ-COMMITTED
# 启用二进制日志记录,用于数据恢复和复制
log-bin = mysql-bin
# 设置二进制日志格式为ROW,提供更精确的数据变更记录
binlog_format = ROW
# 在ROW格式下,记录完整的行图像,便于数据恢复
binlog_row_image = FULL
# 设置二进制日志过期时间为1209600秒(即14天),帮助控制磁盘使用
binlog_expire_logs_seconds = 1209600
# 将master信息存储在表中而不是文件中,提高可靠性和管理便利性
master_info_repository = TABLE
# 将relay log信息存储在表中而不是文件中,提高可靠性和管理便利性
relay_log_info_repository = TABLE
# 启用从库更新的日志记录,支持基于GTID的复制
log_replica_updates = ON
# 启用中继日志恢复功能,在崩溃后自动恢复
relay_log_recovery = 1
# 跳过特定类型的错误,例如DDL语句存在的错误
replica_skip_errors = ddl_exist_errors
# 在每次事务提交时都将缓存的日志刷新到磁盘,保证ACID属性中的D(持久性)
innodb_flush_log_at_trx_commit = 1
# 每次事务提交时同步二进制日志到磁盘,保证数据一致性
sync_binlog = 1
# 设置事务写集提取算法为XXHASH64,用于并行复制和冲突检测
transaction_write_set_extraction = XXHASH64
# 启用全局事务ID模式,允许基于GTID的复制
gtid_mode = on
# 强制GTID的一致性,不允许执行破坏GTID连续性的操作
enforce_gtid_consistency = ON
2.3. 启动容器
在三台主机上执行以下命令启动 MySQL 容器:
sudo docker run \
-u root \
--network=host \
--restart=always \
--name mysql8 \
-v /opt/mysql/conf/my.cnf:/etc/mysql/my.cnf \
-v /opt/mysql/files:/var/lib/mysql-files \
-v /opt/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=q1w2E#R$ \
-d mysql:8.0.27
2.4. 创建用户
执行以下命令进入MySQL容器
sudo docker exec -it mysql8 /bin/bash
mysql -uroot -p -P3309
在三台主机上创建复制用户:
SET SQL_LOG_BIN=0;
CREATE USER rpl_user@'%' IDENTIFIED WITH mysql_native_password BY 'PassWord123_';
GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
GRANT CONNECTION_ADMIN ON *.* TO rpl_user@'%';
GRANT BACKUP_ADMIN ON *.* TO rpl_user@'%';
GRANT GROUP_REPLICATION_STREAM ON *.* TO rpl_user@'%';
GRANT SELECT ON performance_schema.replication_group_members TO rpl_user@'%';
FLUSH PRIVILEGES;
SET SQL_LOG_BIN=1;
三台主机将用户凭据提供给服务器以用于分布式恢复
CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user', SOURCE_PASSWORD='PassWord123_' FOR CHANNEL 'group_replication_recovery';
2.5. 配置 Group Replication
在三台主机安装插件
# 安装插件
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
# 查看插件
SHOW PLUGINS;
在三台主机的 my.cnf
中增加 Group Replication 参数:
# master
group_replication_group_name = "7cf70110-59f9-11ee-a293-246e967fa518"
group_replication_start_on_boot = off
group_replication_local_address = "192.168.3.28:33061"
group_replication_group_seeds = "192.168.3.28:33061,192.168.3.29:33061,192.168.3.30:33061"
group_replication_bootstrap_group = off
# node1
group_replication_group_name = "7cf70110-59f9-11ee-a293-246e967fa518"
group_replication_start_on_boot = off
group_replication_local_address = "192.168.3.29:33061"
group_replication_group_seeds = "192.168.3.28:33061,192.168.3.29:33061,192.168.3.30:33061"
group_replication_bootstrap_group = off
# node2
group_replication_group_name = "7cf70110-59f9-11ee-a293-246e967fa518"
group_replication_start_on_boot = off
group_replication_local_address = "192.168.3.30:33061"
group_replication_group_seeds = "192.168.3.28:33061,192.168.3.29:33061,192.168.3.30:33061"
group_replication_bootstrap_group = off
三台主机重启容器
sudo docker restart mysql8
登录mysql之后查看参数
SHOW VARIABLES LIKE 'group_replication%';
2.6. 启动集群
在 master 上启动集群:
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION USER='rpl_user', PASSWORD='PassWord123_';
SET GLOBAL group_replication_bootstrap_group=OFF;
2.7. 加入集群
在 node1 和 node2 上加入集群:
START GROUP_REPLICATION USER='rpl_user', PASSWORD='PassWord123_';
2.8. 验证集群状态
查看集群状态和事件记录:
SELECT * FROM performance_schema.replication_group_members;
SHOW BINLOG EVENTS;
三.性能优化
在高并发场景下,调整innodb_flush_log_at_trx_commit和sync_binlog这两个参数可以在性能和数据一致性之间找到一个平衡点。
3.1innodb_flush_log_at_trx_commit
这个参数控制着InnoDB存储引擎在事务提交时如何写入和刷新日志缓冲区的数据到磁盘。
- 默认值(1):每次事务提交时都将日志缓冲区的内容写入日志文件,并且同步到磁盘。这是最安全的设置,能确保最高的数据持久性,但会对性能产生较大影响。
- 值为0:每秒将日志缓冲区的数据写入日志文件并同步到磁盘一次,而不是每次事务提交都执行此操作。这提高了性能,但在数据库崩溃时可能会丢失一秒内的事务数据。
- 值为2:每次事务提交时都将日志缓冲区的数据写入日志文件,但并不强制同步到磁盘。这意味着如果操作系统崩溃,可能会丢失最后一段时间的数据,但相比值为0的情况要少一些。
建议调整:
- 如果你的应用可以接受一定程度的数据丢失风险(例如某些非关键交易系统),为了提高性能,可以选择将此参数设置为
2
。这样既保证了较高的事务处理速度,又能在大多数情况下提供足够的数据安全性。 - 对于那些要求极高数据一致性和持久性的应用(如金融系统),则应保持默认值
1
不变。
3.2sync_binlog
该参数决定了MySQL在二进制日志中记录了多少次事务后调用fsync()函数将其同步到磁盘。
- 默认值(1):每次事务提交都会触发同步操作,保证了二进制日志的最大安全性,但是会显著降低写入性能。
- 值大于1:指定每次同步前需要累积多少次事务提交,比如
100
表示每100次事务提交后同步一次。这种方式可以提升性能,但增加了数据丢失的风险。 - 值为0:由操作系统决定何时将二进制日志缓存中的内容同步到磁盘。这种方式可能带来最佳的写入性能,但也是最不安全的选择,因为一旦发生故障,可能导致大量未同步的事务丢失。
建议调整:
- 在追求极致性能的情况下,可以考虑将
sync_binlog
设置为一个较大的数值(如100
或更高),但这意味着你需要接受更高的数据丢失风险。 - 对于需要严格保证数据一致性的环境,应该维持默认值
1
,尽管这样做会影响性能。
四、注意事项
- 网络配置
如果各节点不在同一子网,需在my.cnf文件中配置 group_replication_ip_allowlist 参数,允许节点间通信。
group_replication_ip_allowlist = "127.0.0.1,192.168.3.28,192.168.3.29,192.168.3.30"
- 监控与维护:
使用 MySQL Performance Schema 和监控工具(如 Prometheus + Grafana)实时监控集群状态。
- 本文标签: MySQL 云原生
- 本文链接: https://lanzi.cyou/article/41
- 版权声明: 本文由咖啡豆原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权