1. 项目概述
MySQL数据库作为最流行的开源关系型数据库之一,在企业级应用中扮演着重要角色。随着容器化技术的普及,如何在Docker Swarm集群中部署高可用的MySQL主从架构成为许多DevOps工程师关注的重点。本文将详细介绍两种MySQL复制模式(传统复制和GTID复制)在Swarm环境下的实现方案。
提示:在生产环境中,建议优先考虑GTID复制模式,它提供了更可靠的故障转移机制和复制管理能力。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备
2.1 Docker Swarm集群搭建
首先需要准备至少3个节点的Docker Swarm集群。这里假设我们已经完成了Swarm初始化:
bash复制# 在管理节点执行
docker swarm init --advertise-addr <MANAGER_IP>
# 在工作节点执行
docker swarm join --token <TOKEN> <MANAGER_IP>:2377
验证集群状态:
bash复制docker node ls
2.2 存储卷准备
MySQL数据需要持久化存储,我们为每个节点创建本地卷:
bash复制docker volume create mysql_data
docker volume create mysql_conf
注意:生产环境建议使用网络存储(如NFS)或云存储方案,确保数据高可用。
3. MySQL主从集群部署
3.1 传统复制模式部署
3.1.1 主节点配置
创建主节点服务:
bash复制docker service create \
--name mysql_master \
--mount type=volume,source=mysql_data,destination=/var/lib/mysql \
--mount type=volume,source=mysql_conf,destination=/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=yourpassword \
-e MYSQL_REPLICATION_USER=repl \
-e MYSQL_REPLICATION_PASSWORD=replpassword \
--network mysql_net \
--constraint 'node.role == manager' \
mysql:8.0 \
--server-id=1 \
--log-bin=mysql-bin \
--binlog-format=ROW \
--binlog-row-image=FULL \
--sync-binlog=1
3.1.2 从节点配置
创建从节点服务:
bash复制docker service create \
--name mysql_slave \
--mount type=volume,source=mysql_data,destination=/var/lib/mysql \
--mount type=volume,source=mysql_conf,destination=/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=yourpassword \
--network mysql_net \
--constraint 'node.role == worker' \
mysql:8.0 \
--server-id=2 \
--log-bin=mysql-bin \
--binlog-format=ROW \
--binlog-row-image=FULL \
--read-only=1
3.1.3 配置复制
在主节点执行:
sql复制CREATE USER 'repl'@'%' IDENTIFIED BY 'replpassword';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
SHOW MASTER STATUS;
记录File和Position值,在从节点执行:
sql复制CHANGE MASTER TO
MASTER_HOST='mysql_master',
MASTER_USER='repl',
MASTER_PASSWORD='replpassword',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
START SLAVE;
3.2 GTID复制模式部署
3.2.1 主节点配置
修改主节点配置,添加GTID相关参数:
ini复制[mysqld]
server-id=1
log-bin=mysql-bin
binlog-format=ROW
binlog-row-image=FULL
sync-binlog=1
gtid-mode=ON
enforce-gtid-consistency=ON
3.2.2 从节点配置
从节点配置:
ini复制[mysqld]
server-id=2
log-bin=mysql-bin
binlog-format=ROW
binlog-row-image=FULL
read-only=1
gtid-mode=ON
enforce-gtid-consistency=ON
log-slave-updates=ON
skip-slave-start=1
3.2.3 配置GTID复制
在从节点执行:
sql复制CHANGE MASTER TO
MASTER_HOST='mysql_master',
MASTER_USER='repl',
MASTER_PASSWORD='replpassword',
MASTER_AUTO_POSITION=1;
START SLAVE;
4. 集群管理与监控
4.1 复制状态检查
检查复制状态:
sql复制SHOW SLAVE STATUS\G
重点关注:
- Slave_IO_Running: Yes
- Slave_SQL_Running: Yes
- Seconds_Behind_Master: 0
4.2 故障转移处理
4.2.1 主节点故障
- 选择一个从节点提升为新主节点:
sql复制STOP SLAVE;
RESET MASTER;
SET GLOBAL read_only=OFF;
- 其他从节点重新指向新主节点:
sql复制STOP SLAVE;
CHANGE MASTER TO MASTER_HOST='new_master';
START SLAVE;
4.2.2 从节点故障
只需重新启动从节点服务,GTID复制会自动同步缺失的事务。
5. 性能优化建议
5.1 参数调优
ini复制[mysqld]
innodb_buffer_pool_size=4G
innodb_log_file_size=1G
sync_binlog=1
innodb_flush_log_at_trx_commit=1
5.2 网络优化
使用Docker overlay网络的加密选项:
bash复制docker network create --opt encrypted --driver overlay mysql_net
5.3 监控方案
推荐使用Prometheus + Grafana监控MySQL复制状态:
yaml复制version: '3.8'
services:
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana
ports:
- "3000:3000"
6. 常见问题与解决方案
6.1 复制延迟问题
可能原因:
- 网络带宽不足
- 从节点I/O性能差
- 大事务执行
解决方案:
- 增加网络带宽
- 使用SSD存储
- 拆分大事务
6.2 GTID不一致错误
错误示例:
code复制Error 'Cannot execute the current event group in the parallel mode...'
解决方法:
sql复制STOP SLAVE;
SET GLOBAL slave_parallel_workers=0;
START SLAVE;
6.3 容器重启后复制中断
解决方案:
- 使用--restart=always策略
- 配置健康检查
- 使用init容器等待主节点就绪
7. 安全最佳实践
7.1 网络隔离
bash复制docker network create --driver overlay --attachable mysql_net
7.2 加密连接
配置SSL加密复制:
sql复制CHANGE MASTER TO
MASTER_SSL=1,
MASTER_SSL_CA='/etc/mysql/ssl/ca.pem',
MASTER_SSL_CERT='/etc/mysql/ssl/client-cert.pem',
MASTER_SSL_KEY='/etc/mysql/ssl/client-key.pem';
7.3 定期备份
使用mysqldump进行逻辑备份:
bash复制docker exec mysql_master mysqldump -uroot -p --all-databases > backup.sql
8. 扩展方案:MySQL Router集成
8.1 MySQL Router部署
bash复制docker run -d --name mysql_router \
-e MYSQL_ROUTER_BOOTSTRAP="mysql_master:3306" \
-e MYSQL_ROUTER_USER="router" \
-e MYSQL_ROUTER_PASSWORD="routerpass" \
-p 6446:6446 -p 6447:6447 -p 6448:6448 -p 6449:6449 \
mysql/mysql-router:8.0
8.2 读写分离配置
router配置示例:
ini复制[routing:read_write]
bind_address=0.0.0.0
bind_port=6446
destinations=mysql_master:3306
protocol=classic
[routing:read_only]
bind_address=0.0.0.0
bind_port=6447
destinations=mysql_slave:3306
protocol=classic
9. 维护与升级策略
9.1 滚动升级方案
- 先升级从节点:
bash复制docker service update --image mysql:8.0.x mysql_slave
- 故障转移后升级原主节点:
bash复制docker service update --image mysql:8.0.x mysql_master
9.2 配置变更管理
使用配置注入:
bash复制docker config create mysql_conf ./my.cnf
docker service update --config-add source=mysql_conf,target=/etc/mysql/conf.d/my.cnf mysql_master
10. 实际应用案例
在某电商平台的实际部署中,我们采用了以下架构:
- 3节点Swarm集群
- 1主2从GTID复制
- MySQL Router实现读写分离
- Prometheus监控告警
该架构支撑了黑五期间每秒5000+的查询量,复制延迟始终保持在1秒以内。
