1. 项目概述
在当今的互联网应用开发中,数据库的高可用性和负载均衡是每个开发者都需要面对的核心问题。MySQL作为最流行的开源关系型数据库之一,其主从复制架构能够有效解决这两个需求。而Docker作为轻量级的容器化技术,为我们快速搭建和测试这种架构提供了极大的便利。
这个项目将展示如何利用Docker容器技术,在单台开发机上快速搭建一个MySQL一主两从的复制环境。这种配置不仅适用于开发测试环境,其原理同样可以应用于生产环境的部署。通过这个实践,你将掌握Docker网络配置、MySQL复制参数调优以及主从状态监控等实用技能。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与基础配置
2.1 Docker环境搭建
首先确保你的系统已经安装了Docker引擎。对于Windows和Mac用户,建议使用Docker Desktop;Linux用户可以直接安装Docker CE。安装完成后,通过以下命令验证安装是否成功:
bash复制docker --version
docker-compose --version
注意:如果遇到"Docker Desktop failed to start because virtualisation support wasn't detected"错误,需要在BIOS中启用虚拟化支持(VT-x/AMD-V)。
2.2 网络配置
为了让三个MySQL容器能够互相通信,我们需要创建一个专用的Docker网络:
bash复制docker network create mysql-replication
这个网络将用于主从服务器之间的数据同步通信,与宿主机的网络隔离,既保证了安全性又避免了端口冲突。
2.3 MySQL镜像选择
官方MySQL镜像提供了多个版本标签,建议选择与你的应用兼容的特定版本。这里我们使用MySQL 8.0:
bash复制docker pull mysql:8.0
3. 主服务器配置
3.1 启动主服务器容器
使用以下命令启动MySQL主服务器:
bash复制docker run -d --name mysql-master \
--network mysql-replication \
-e MYSQL_ROOT_PASSWORD=masterpassword \
-v mysql-master-data:/var/lib/mysql \
-p 3306:3306 \
mysql:8.0 \
--server-id=1 \
--log-bin=mysql-bin \
--binlog-format=ROW \
--binlog-do-db=replication_db
关键参数说明:
--server-id=1:唯一标识主服务器--log-bin:启用二进制日志,这是复制的基础--binlog-do-db:指定需要复制的数据库
3.2 主服务器用户配置
进入主服务器容器创建复制专用用户:
bash复制docker exec -it mysql-master mysql -uroot -pmasterpassword
在MySQL命令行执行:
sql复制CREATE USER 'repl'@'%' IDENTIFIED BY 'replpassword';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
3.3 获取主服务器状态
在主服务器上执行以下命令,记录File和Position值,从服务器配置时需要:
sql复制SHOW MASTER STATUS;
输出示例:
code复制+------------------+----------+------------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+------------------+------------------+
| mysql-bin.000003 | 785 | replication_db | |
+------------------+----------+------------------+------------------+
4. 从服务器配置
4.1 启动第一个从服务器
bash复制docker run -d --name mysql-slave1 \
--network mysql-replication \
-e MYSQL_ROOT_PASSWORD=slavepassword \
-v mysql-slave1-data:/var/lib/mysql \
-p 3307:3306 \
mysql:8.0 \
--server-id=2 \
--log-bin=mysql-bin \
--relay-log=mysql-relay-bin \
--read-only=1
4.2 启动第二个从服务器
bash复制docker run -d --name mysql-slave2 \
--network mysql-replication \
-e MYSQL_ROOT_PASSWORD=slavepassword \
-v mysql-slave2-data:/var/lib/mysql \
-p 3308:3306 \
mysql:8.0 \
--server-id=3 \
--log-bin=mysql-bin \
--relay-log=mysql-relay-bin \
--read-only=1
关键参数说明:
--server-id:必须唯一且不同于主服务器--read-only=1:从服务器设为只读模式--relay-log:指定中继日志位置
4.3 配置从服务器复制
分别进入两个从服务器容器配置复制:
bash复制docker exec -it mysql-slave1 mysql -uroot -pslavepassword
在MySQL命令行执行(使用之前记录的File和Position值):
sql复制CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='repl',
MASTER_PASSWORD='replpassword',
MASTER_LOG_FILE='mysql-bin.000003',
MASTER_LOG_POS=785;
START SLAVE;
对第二个从服务器重复相同操作。
5. 验证复制状态
5.1 检查从服务器状态
在每个从服务器上执行:
sql复制SHOW SLAVE STATUS\G
重点关注以下字段:
Slave_IO_Running: YesSlave_SQL_Running: YesSeconds_Behind_Master: 0或很小的数值
5.2 测试数据同步
在主服务器上创建测试数据库和表:
sql复制CREATE DATABASE replication_db;
USE replication_db;
CREATE TABLE test(id INT PRIMARY KEY, name VARCHAR(20));
INSERT INTO test VALUES(1, 'master');
然后在从服务器上查询,应该能看到相同的数据。
6. 高级配置与优化
6.1 复制过滤配置
可以通过以下参数控制哪些数据库或表需要复制:
ini复制# 只复制特定数据库
replicate-do-db=db1
replicate-do-db=db2
# 忽略特定数据库
replicate-ignore-db=mysql
replicate-ignore-db=sys
6.2 半同步复制
为了提高数据安全性,可以配置半同步复制,确保至少一个从服务器接收到数据后主服务器才提交事务:
在主服务器my.cnf中添加:
ini复制plugin-load="rpl_semi_sync_master=semisync_master.so"
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=10000
在从服务器my.cnf中添加:
ini复制plugin-load="rpl_semi_sync_slave=semisync_slave.so"
rpl_semi_sync_slave_enabled=1
6.3 复制监控
可以通过以下SQL监控复制延迟和状态:
sql复制SHOW REPLICA STATUS;
SHOW PROCESSLIST;
SELECT * FROM performance_schema.replication_applier_status_by_worker;
7. 常见问题与解决方案
7.1 复制中断问题
当从服务器出现复制错误时,通常会停止复制。可以通过以下步骤恢复:
- 查看错误原因:
sql复制SHOW SLAVE STATUS\G
- 跳过特定错误(谨慎使用):
sql复制STOP SLAVE;
SET GLOBAL sql_slave_skip_counter = 1;
START SLAVE;
- 或者重新配置复制:
sql复制STOP SLAVE;
RESET SLAVE;
CHANGE MASTER TO ...; -- 使用新的binlog位置
START SLAVE;
7.2 数据不一致问题
如果发现主从数据不一致,可以重新初始化从服务器:
- 在主服务器上锁定表并导出数据:
sql复制FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS; -- 记录位置
-- 在另一个会话中执行mysqldump
UNLOCK TABLES;
- 在从服务器上停止复制并导入数据:
sql复制STOP SLAVE;
RESET SLAVE;
-- 导入数据
CHANGE MASTER TO ...; -- 使用新的binlog位置
START SLAVE;
7.3 网络问题
如果容器间无法通信:
- 检查网络连接:
bash复制docker network inspect mysql-replication
- 测试容器间连通性:
bash复制docker exec -it mysql-master ping mysql-slave1
- 确保防火墙没有阻止容器网络通信
8. 性能优化建议
8.1 资源配置优化
根据负载情况调整容器资源限制:
bash复制docker update --cpus 2 --memory 2g mysql-master
docker update --cpus 1 --memory 1g mysql-slave1
docker update --cpus 1 --memory 1g mysql-slave2
8.2 MySQL参数调优
根据工作负载调整以下参数:
ini复制# 主服务器
innodb_flush_log_at_trx_commit=1
sync_binlog=1
binlog_group_commit_sync_delay=100
binlog_group_commit_sync_no_delay_count=10
# 从服务器
slave_parallel_workers=4
slave_parallel_type=LOGICAL_CLOCK
8.3 监控与告警
建议配置以下监控项:
- 复制延迟时间
- 从服务器IO/SQL线程状态
- 主服务器binlog位置增长
- 网络延迟和吞吐量
可以使用Prometheus + Grafana搭建监控系统,或者使用现成的MySQL监控工具如Percona Monitoring and Management。
9. 生产环境部署建议
虽然我们在开发环境中使用Docker搭建了一主两从架构,但生产环境部署需要考虑更多因素:
- 高可用性:考虑使用MySQL Group Replication或InnoDB Cluster替代传统复制
- 数据安全:定期备份binlog和数据库快照
- 监控告警:实现全面的监控和自动故障转移
- 资源隔离:主从服务器应该部署在不同的物理节点上
- 读写分离:使用ProxySQL或MySQL Router实现自动的读写分离
10. 容器化特定问题处理
10.1 数据持久化
确保使用Docker卷持久化MySQL数据:
bash复制docker volume create mysql-master-data
docker volume create mysql-slave1-data
docker volume create mysql-slave2-data
10.2 容器重启策略
配置容器自动重启:
bash复制docker update --restart unless-stopped mysql-master
docker update --restart unless-stopped mysql-slave1
docker update --restart unless-stopped mysql-slave2
10.3 使用Docker Compose
为了便于管理,可以使用docker-compose.yml文件定义整个架构:
yaml复制version: '3.8'
services:
mysql-master:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: masterpassword
volumes:
- mysql-master-data:/var/lib/mysql
networks:
- mysql-replication
command:
- --server-id=1
- --log-bin=mysql-bin
- --binlog-format=ROW
ports:
- "3306:3306"
mysql-slave1:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: slavepassword
volumes:
- mysql-slave1-data:/var/lib/mysql
networks:
- mysql-replication
command:
- --server-id=2
- --log-bin=mysql-bin
- --relay-log=mysql-relay-bin
- --read-only=1
ports:
- "3307:3306"
mysql-slave2:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: slavepassword
volumes:
- mysql-slave2-data:/var/lib/mysql
networks:
- mysql-replication
command:
- --server-id=3
- --log-bin=mysql-bin
- --relay-log=mysql-relay-bin
- --read-only=1
ports:
- "3308:3306"
volumes:
mysql-master-data:
mysql-slave1-data:
mysql-slave2-data:
networks:
mysql-replication:
driver: bridge
启动整个架构只需运行:
bash复制docker-compose up -d
