Linux中MySQL 双主复制(互为主从)配置指南(详细过程)!
'# Linux中MySQL 双主复制(互为主从)配置指南(详细过程)!
一、背景与问题
在分布式系统中,MySQL双主复制(Mutual Master-Slave Replication)是一种常见的数据同步方案。这种架构允许两个MySQL实例互为主从,数据在两者之间双向同步。这种模式特别适用于需要高可用性、双向数据同步的场景,例如:
- 双活数据中心的数据库同步
- 需要跨地域数据分发的业务
- 前后端系统之间的数据对等同步
但这种架构也存在挑战:
- 数据一致性风险:两个主库同时写入可能导致主键冲突
- 复制延迟:网络延迟可能导致数据不同步
- 故障恢复复杂:需要处理主从切换时的脑裂问题
- 性能损耗:双方向复制会增加服务器负载
本指南将深入解析其原理,提供完整配置方案,并分析实际应用中的最佳实践与风险控制。
二、基本原理
MySQL复制基于binlog(二进制日志)机制实现,双主复制的核心原理如下:
- 日志记录:每个主库将所有变更操作记录到binlog中
- 日志传输:通过复制线程将binlog传输到对方服务器
- 日志重放:从库将接收到的binlog事件重放至数据库
双主复制的关键在于每个实例同时作为主库和从库,需要特别注意以下配置要点:
- server-id:每个实例必须有唯一的server-id
- binlog格式:必须配置为ROW格式(基于行的复制)
- 复制方式:支持基于GTID(全局事务标识符)或基于位置的复制
三、环境准备
系统要求
- 操作系统:CentOS 7.x 或 Ubuntu 20.04+
- MySQL版本:8.0.x(支持GTID)
- 网络:确保两台服务器之间能互相访问(如192.168.1.101和192.168.1.102)
安装MySQL
# 安装MySQL
sudo yum install -y mariadb-server # CentOS
# 或
sudo apt-get install -y mysql-server # Ubuntu
# 启动并设置开机启动
sudo systemctl start mysqld
sudo systemctl enable mysqld配置防火墙
# 允许MySQL端口通信
sudo firewall-cmd --permanent --add-port=3306/tcp
sudo firewall-cmd --reload四、核心实现
1. 配置文件修改(my.cnf)
# /etc/my.cnf 或 /etc/mysql/my.cnf
[mysqld]
server-id=101 # 主库A的server-id
log-bin=mysql-bin
binlog-format=ROW
sync-binlog=1
innodb_flush_log_at_trx_commit=1# 另一台服务器配置文件
[mysqld]
server-id=102 # 主库B的server-id
log-bin=mysql-bin
binlog-format=ROW
sync-binlog=1
innodb_flush_log_at_trx_commit=1关键配置说明:
server-id:必须确保两台服务器的server-id不同binlog-format=ROW:必须使用基于行的复制格式sync-binlog=1:确保事务日志立即刷新到磁盘,提高数据可靠性
2. 创建复制用户
-- 在主库A执行
CREATE USER 'repl'@'192.168.1.102' IDENTIFIED BY 'StrongPassword!';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.102';
FLUSH PRIVILEGES;-- 在主库B执行
CREATE USER 'repl'@'192.168.1.101' IDENTIFIED BY 'StrongPassword!';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.101';
FLUSH PRIVILEGES;安全注意事项:
- 使用专用复制账户,避免使用root用户
- 密码建议使用强密码,且定期更换
- 限制复制账户的IP访问范围
3. 配置主从关系
-- 在主库A执行(设置从库B连接)
CHANGE MASTER TO
MASTER_HOST='192.168.1.102',
MASTER_USER='repl',
MASTER_PASSWORD='StrongPassword!',
MASTER_AUTO_POSITION=1; -- 使用GTID自动定位
-- 在主库B执行(设置从库A连接)
CHANGE MASTER TO
MASTER_HOST='192.168.1.101',
MASTER_USER='repl',
MASTER_PASSWORD='StrongPassword!',
MASTER_AUTO_POSITION=1;关键参数说明:
MASTER_AUTO_POSITION=1:使用GTID进行自动定位,避免基于位置的复制错误- 确保两个实例的binlog格式一致,且均为ROW格式
4. 启动复制进程
-- 在从库A执行(即主库B)
START SLAVE;
-- 在从库B执行(即主库A)
START SLAVE;5. 验证复制状态
-- 在从库A执行
SHOW SLAVE STATUS\G
-- 在从库B执行
SHOW SLAVE STATUS\G关键字段检查:
Slave_IO_Running: YesSlave_SQL_Running: YesSeconds_Behind_Master: 0(表示同步正常)
五、完整案例
场景描述
两个MySQL实例(192.168.1.101和192.168.1.102)建立双主复制,数据双向同步。测试写入操作是否在两个实例中同步。
实施步骤
配置文件修改
- 修改两台服务器的my.cnf,设置不同的server-id
- 确保binlog格式为ROW
创建复制用户
- 在两台服务器分别创建复制账户
配置主从关系
- 主库A配置从库B连接
- 主库B配置从库A连接
启动复制进程
- 在两台从库执行START SLAVE
验证复制
- 在任意实例插入数据,检查另一个实例是否同步
测试代码
-- 在实例A执行
INSERT INTO test_table (id, name) VALUES (1, 'Alice');
-- 在实例B执行
SELECT * FROM test_table;预期结果:两个实例都能看到插入的记录
六、源码解析
1. binlog格式选择
MySQL的binlog有三种格式:STATEMENT、ROW、MIXED。双主复制必须使用ROW格式,因为:
- STATEMENT格式可能导致复制不一致(如函数返回值不同)
- ROW格式记录每行数据变更,确保精确同步
- MIXED格式在不确定时可能切换格式,导致复制错误
2. GTID机制
MASTER_AUTO_POSITION=1启用GTID自动定位,其原理是:
- 每个事务都有唯一的GTID标识(server_uuid:transaction_id)
- 当从库需要同步时,自动定位到最近的GTID位置
- 避免基于位置的复制时因日志文件增长导致的定位错误
3. 复制线程工作流程
MySQL复制包含两个线程:
- IO线程:负责从主库读取binlog并保存到中继日志
- SQL线程:负责从中继日志读取事件并重放到数据库
双主复制中,每个实例同时作为主库和从库,需要同时运行这两个线程。
七、进阶使用
1. 数据库分片
在双主复制基础上,可以结合分片技术实现分布式数据库:
-- 分片规则示例(按用户ID分片)
SELECT * FROM user_table WHERE id % 2 = 0; -- 分片到实例A
SELECT * FROM user_table WHERE id % 2 = 1; -- 分片到实例B2. 增加监控机制
# 使用Prometheus + Grafana监控复制延迟
import mysql.connector
def check_slave_status(host, user, password):
conn = mysql.connector.connect(
host=host,
user=user,
password=password
)
cursor = conn.cursor()
cursor.execute("SHOW SLAVE STATUS\\G")
result = cursor.fetchall()
cursor.close()
conn.close()
return result3. 自动故障转移
# 使用Keepalived实现主从切换
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.1.100
}
}八、性能与工程实践
1. 性能优化策略
| 优化项 | 方法 | 效果 |
|---|---|---|
| binlog压缩 | 使用log_compression=1 | 减少网络传输量 |
| 复制线程并行 | 调整slave_parallel_workers | 提高复制效率 |
| 网络优化 | 使用sync_master_info=0 | 减少IO开销 |
| 索引优化 | 为复制表创建适当索引 | 提高SQL执行效率 |
2. 异常处理机制
-- 设置复制错误自动停止
SET GLOBAL sql_slave_skip_counter = 1; -- 跳过当前错误
STOP SLAVE;
START SLAVE;3. 安全加固措施
使用SSL加密复制连接:
CHANGE MASTER TO MASTER_SSL=1, MASTER_SSL_CA='/etc/ssl/certs/ca-cert.pem', MASTER_SSL_CERT='/etc/ssl/certs/client-cert.pem', MASTER_SSL_KEY='/etc/ssl/private/client-key.pem';定期清理旧日志:
mysql -e "PURGE BINARY LOGS TO 'mysql-bin.010';"
九、常见问题与踩坑
1. 主从不同步问题
常见错误:
Last_Error: error during connection to masterLast_Error: Could not connect to master
解决方法:
- 检查防火墙设置
- 确认复制账户权限
- 检查
server-id是否冲突 - 查看
/var/log/mysqld.log日志
2. 主键冲突处理
问题场景:两个实例同时插入相同主键的记录
解决方案:
- 使用GTID复制,确保事务顺序一致
- 在应用层增加分布式ID生成机制(如Snowflake)
- 在数据库层面使用
ON DUPLICATE KEY UPDATE
3. 复制延迟过大
优化建议:
- 使用
SHOW SLAVE STATUS监控Seconds_Behind_Master - 调整
slave_parallel_workers参数 - 增加硬件资源(如SSD硬盘)
- 使用压缩传输(
log_compression=1)
十、最佳实践
适用场景
- 需要双向数据同步的业务:如双活数据中心
- 前后端系统对等数据交换:如微服务架构中的数据对等同步
- 需要高可用性的场景:结合Keepalived实现自动切换
不适用场景
- 数据量较小的系统:复制带来的额外开销可能不划算
- 单向数据流场景:更适合使用单主从架构
- 需要强一致性保障的场景:建议使用分布式事务(如XA协议)
推荐配置方案
| 配置项 | 推荐值 | 说明 |
|---|---|---|
| binlog_format | ROW | 确保精确复制 |
| sync_binlog | 1 | 提高数据可靠性 |
| innodb_flush_log_at_trx_commit | 1 | 确保事务提交立即刷新 |
| master_auto_position | 1 | 自动定位GTID |
| slave_parallel_workers | 4 | 提高复制效率 |
十一、总结
MySQL双主复制是一种强大的数据同步方案,但需要充分理解其原理和潜在风险。本文详细讲解了其工作原理、配置方法、常见问题和优化策略,通过实际案例帮助读者掌握配置技巧。
在实际应用中,建议:
- 严格控制复制账户权限,避免安全风险
- 定期监控复制延迟,确保数据一致性
- 结合监控系统,实现自动化运维
- 在高可用架构中,配合Keepalived等工具实现自动切换
- 在数据量较大时,考虑分片或中间件方案
对于需要双向同步的业务场景,双主复制是值得考虑的解决方案,但需根据业务需求权衡利弊,避免在不适用的场景中使用。
评论已关闭