1. Docker搭建MySQL一主两从架构全指南
在分布式系统和高并发场景下,数据库的读写分离已经成为标配方案。我最近在电商项目中刚用Docker完成了MySQL一主两从的集群搭建,整个过程踩了不少坑,也积累了些实战经验。这种架构不仅能有效分担主库压力,还能实现故障自动切换,对于日均百万级查询的系统来说,性能提升非常明显。
相比传统虚拟机部署,Docker容器化方案的优势在于秒级启动、资源隔离和配置固化。特别是当你需要快速扩展从库节点时,Docker的镜像复用特性可以让新增从库的部署时间从小时级缩短到分钟级。下面我就详细拆解整个搭建过程,包括那些官方文档没写的细节问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与基础配置
2.1 Docker环境调优
很多人直接apt install docker-ce就完事了,其实生产环境需要特别关注几个参数。建议在/etc/docker/daemon.json中添加以下配置:
json复制{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
},
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 65535,
"Soft": 65535
}
}
}
重要提示:Windows/Mac用户如果遇到"virtualisation support not detected"错误,需要:
- BIOS中开启VT-x/AMD-V虚拟化支持
- 关闭Hyper-V相关功能
- 以管理员身份运行
bcdedit /set hypervisorlaunchtype off
2.2 MySQL镜像选择策略
官方mysql镜像有多个版本标签,生产环境建议锁定具体小版本:
bash复制# 主库使用完整功能版
docker pull mysql:8.0.34
# 从库可以使用精简版
docker pull mysql:8.0.34-oracle
不同版本的内存占用差异很大,实测8.0.34标准版容器空载需要400MB内存,而oracle精简版只需280MB。如果资源紧张,从库完全可以选用精简版。
3. 主库配置深度解析
3.1 主库核心参数
创建主库容器时,这几个参数必须配置:
bash复制docker run -d \
--name=mysql-master \
-v /data/mysql/master:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=Master@123 \
-e MYSQL_REPLICATION_USER=repl \
-e MYSQL_REPLICATION_PASSWORD=Repl@123 \
-p 3306:3306 \
mysql:8.0.34 \
--server-id=1 \
--log-bin=mysql-bin \
--binlog-format=ROW \
--binlog-row-image=FULL \
--gtid-mode=ON \
--enforce-gtid-consistency=ON
关键参数说明:
server-id=1:集群内唯一标识,主从不能重复binlog-format=ROW:确保数据变更精准复制gtid-mode=ON:全局事务标识,故障切换时不会丢失数据
3.2 主库用户权限配置
很多教程只给repl用户REPLICATION SLAVE权限,其实生产环境需要更完整的授权:
sql复制CREATE USER 'repl'@'%' IDENTIFIED BY 'Repl@123';
GRANT REPLICATION SLAVE, REPLICATION CLIENT, SELECT, RELOAD ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
额外授予SELECT和RELOAD权限是为了方便后期做数据校验和热加载配置。
4. 从库配置实战技巧
4.1 从库初始化方案对比
从库数据初始化有三种方式,各有优劣:
| 方式 | 耗时 | 锁表 | 适用场景 |
|---|---|---|---|
| mysqldump | 长 | 是 | 小数据量(<10GB) |
| xtrabackup | 中 | 否 | 大数据量 |
| 主库快照 | 短 | 是 | 测试环境 |
推荐使用xtrabackup方案,虽然步骤复杂但不会锁主库:
bash复制# 在主库执行
docker exec mysql-master \
xtrabackup --backup --target-dir=/var/lib/mysql/backup \
--user=root --password=Master@123
# 在从库主机还原
docker run -d \
--name=mysql-slave1 \
-v /data/mysql/slave1:/var/lib/mysql \
mysql:8.0.34-oracle \
--server-id=2 \
--read-only=ON
docker cp backup.tar mysql-slave1:/var/lib/mysql/
docker exec mysql-slave1 tar xvf /var/lib/mysql/backup.tar
4.2 从库关键参数
从库启动时必须配置的额外参数:
ini复制[mysqld]
skip-slave-start=ON # 防止自动启动复制
relay-log=mysql-relay-bin
log-slave-updates=ON # 级联复制时需要
slave-parallel-workers=4 # 并行复制线程
特别是skip-slave-start,可以避免数据未完全恢复时就启动复制导致的数据不一致。
5. 主从连接与监控
5.1 建立复制链路
在从库上执行这条命令前,务必先确认主库的GTID位置:
sql复制CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='repl',
MASTER_PASSWORD='Repl@123',
MASTER_AUTO_POSITION=1;
START SLAVE;
使用MASTER_AUTO_POSITION=1比传统binlog位置更可靠,特别是在网络闪断后重连时。
5.2 监控方案推荐
除了常规的SHOW SLAVE STATUS,建议配置Prometheus+Granfa监控:
yaml复制# docker-compose监控服务
monitoring:
image: prom/mysqld-exporter
environment:
DATA_SOURCE_NAME: "exporter:Exporter123@(mysql-master:3306)/"
ports:
- "9104:9104"
关键监控指标:
mysql_slave_status_sql_thread_runningmysql_slave_status_seconds_behind_mastermysql_global_status_innodb_row_lock_time_avg
6. 故障排查实录
6.1 典型错误处理
错误1:Slave_SQL_Running=No, Last_Error=1032
这是从库找不到要删除的记录,解决方法:
sql复制STOP SLAVE;
SET GLOBAL sql_slave_skip_counter=1;
START SLAVE;
如果频繁出现,需要检查主从数据一致性。
错误2:认证失败
检查主库的SHOW MASTER STATUS和从库的SHOW SLAVE STATUS中的Master_User是否一致。MySQL8.0默认使用caching_sha2_password认证,可能需要:
sql复制ALTER USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'Repl@123';
6.2 数据一致性校验
推荐使用pt-table-checksum工具:
bash复制docker run -it \
--network=host \
percona/percona-toolkit \
pt-table-checksum \
h=mysql-master,u=root,p=Master@123 \
--databases=production_db \
--no-check-binlog-format
校验完成后,用pt-table-sync同步差异数据。
7. 性能优化要点
7.1 主库写入优化
在my.cnf中添加:
ini复制[mysqld]
sync_binlog=1 # 确保binlog落盘
innodb_flush_log_at_trx_commit=1
binlog_group_commit_sync_delay=100 # 组提交延迟(微秒)
binlog_group_commit_sync_no_delay_count=10
7.2 从库读取优化
从库配置:
ini复制[mysqld]
slave_parallel_workers=8
slave_parallel_type=LOGICAL_CLOCK
innodb_read_only=ON
query_cache_size=0 # 8.0已移除,但需要显式禁用
特别提醒:从库的innodb_buffer_pool_size可以设置得比主库大,因为从库只有读操作。
8. 高可用方案设计
8.1 故障自动切换
建议使用Orchestrator工具管理故障转移:
yaml复制services:
orchestrator:
image: github/orchestrator
environment:
ORC_TOPOLOGY_USER: root
ORC_TOPOLOGY_PASSWORD: Master@123
ports:
- "3000:3000"
配置策略:
- 自动检测主库宕机
- 提升延迟最小的从库为新主库
- 自动重建其他从库的复制关系
8.2 读写分离实现
使用ProxySQL实现智能路由:
sql复制INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES
(10,'mysql-master',3306),
(20,'mysql-slave1',3306),
(20,'mysql-slave2',3306);
INSERT INTO mysql_query_rules (rule_id,active,match_pattern,destination_hostgroup,apply) VALUES
(1,1,'^SELECT.*FOR UPDATE',10,1),
(2,1,'^SELECT',20,1);
这样所有SELECT请求会自动路由到从库,写操作和加锁读会发给主库。
