meta-description: 使用Docker Compose部署MySQL主从复制完整教程,详解读写分离配置和故障转移。
keywords: Docker Compose,MySQL主从,读写分离,数据库集群,主从复制
# 使用Docker Compose部署MySQL主从复制
本文详细介绍使用Docker Compose部署MySQL主从复制架构,实现读写分离和高可用。
## 主从复制原理
| 角色 | 作用 | 说明 |
|------|------|------|
| Master | 主库 | 处理写操作,记录binlog |
| Slave | 从库 | 拉取binlog,重放SQL |
| 延迟 | 复制延迟 | 通常<1秒 |
## 目录结构
mysql-replication/
├── docker-compose.yml
├── master/
│ ├── my.cnf
│ └── init.sql
├── slave/
│ ├── my.cnf
│ └── init.sql
└── .env
## docker-compose.yml
version: '3.8'
services:
mysql-master:
image: mysql:8.0
container_name: mysql-master
restart: always
environment:
MYSQL_ROOT_PASSWORD: master_root_pass
MYSQL_DATABASE: wordpress
MYSQL_USER: wp_user
MYSQL_PASSWORD: wp_pass
volumes:
- ./master/my.cnf:/etc/mysql/conf.d/my.cnf
- ./master/init.sql:/docker-entrypoint-initdb.d/init.sql
- master-data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- mysql-replication
mysql-slave:
image: mysql:8.0
container_name: mysql-slave
restart: always
environment:
MYSQL_ROOT_PASSWORD: slave_root_pass
volumes:
- ./slave/my.cnf:/etc/mysql/conf.d/my.cnf
- ./slave/init.sql:/docker-entrypoint-initdb.d/init.sql
- slave-data:/var/lib/mysql
ports:
- "3307:3306"
networks:
- mysql-replication
depends_on:
- mysql-master
volumes:
master-data:
slave-data:
networks:
mysql-replication:
driver: bridge
## Master配置
### master/my.cnf
[mysqld]
# 服务器ID(集群中唯一)
server-id = 1
# 开启binlog
log_bin = /var/log/mysql/mysql-bin.log
# binlog格式(ROW推荐)
binlog_format = ROW
# 同步刷盘
sync_binlog = 1
# 需要复制的数据库
binlog_do_db = wordpress
# 忽略的数据库
binlog_ignore_db = mysql
binlog_ignore_db = information_schema
binlog_ignore_db = performance_schema
# 字符集
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
### master/init.sql
-- 创建复制用户(Slave用)
CREATE USER 'repl'@'%' IDENTIFIED BY 'repl_password';
-- 授予复制权限
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
-- 刷新权限
FLUSH PRIVILEGES;
-- 创建用于读操作的用户
CREATE USER 'wp_read'@'%' IDENTIFIED BY 'read_password';
GRANT SELECT ON wordpress.* TO 'wp_read'@'%';
FLUSH PRIVILEGES;
## Slave配置
### slave/my.cnf
[mysqld]
# 服务器ID(集群中唯一)
server-id = 2
# 中继日志
relay_log = /var/log/mysql/relay-bin
# 只读模式
read_only = 1
# 超级用户也只读(可选)
super_read_only = 1
# 需要复制的数据库
replicate_do_db = wordpress
# 忽略的表
replicate_ignore_table = wordpress.wp_options
# 并行复制
slave_parallel_workers = 4
slave_parallel_type = LOGICAL_CLOCK
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
### slave/init.sql
-- 配置主库信息(Docker网络内用服务名)
CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='repl',
MASTER_PASSWORD='repl_password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=156;
-- 启动复制
START SLAVE;
## 启动集群
# 启动Master
docker-compose up -d mysql-master
# 等待Master完全启动
docker-compose logs -f mysql-master
# 看到 "ready for connections" 后继续
# 启动Slave
docker-compose up -d mysql-slave
# 查看状态
docker-compose ps
## 验证主从复制
### 在Master上操作
# 进入Master容器
docker exec -it mysql-master mysql -uroot -pmaster_root_pass
# 查看Master状态
SHOW MASTER STATUS\G
/*
File: mysql-bin.000001
Position: 156
Binlog_Do_DB: wordpress
*/
# 创建测试数据
USE wordpress;
CREATE TABLE test_repl (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50));
INSERT INTO test_repl (name) VALUES ('replication_test');
### 在Slave上验证
# 进入Slave容器
docker exec -it mysql-slave mysql -uroot -pslave_root_pass
# 查看Slave状态
SHOW SLAVE STATUS\G
/*
关键字段:
Slave_IO_Running: Yes ← 必须为Yes
Slave_SQL_Running: Yes ← 必须为Yes
Seconds_Behind_Master: 0 ← 延迟秒数
Last_Error: ← 应为空
*/
# 验证数据同步
USE wordpress;
SELECT * FROM test_repl;
-- 应该能看到在Master插入的数据
## WordPress配置读写分离
### wp-config.php配置
// 主库(写)
define('DB_HOST', 'mysql-master:3306');
// 使用插件实现读写分离,或手动配置:
// 推荐插件:HyperDB 或 LudicrousDB
### 使用HyperDB插件
// hyperdb-config.php
// 写服务器(主库)
$wpdb->add_database(array(
'host' => 'mysql-master:3306',
'user' => 'wp_user',
'password' => 'wp_pass',
'name' => 'wordpress',
'write' => 1,
'read' => 1, // 主库也参与读(可选)
));
// 读服务器(从库)
$wpdb->add_database(array(
'host' => 'mysql-slave:3306',
'user' => 'wp_read',
'password' => 'read_password',
'name' => 'wordpress',
'write' => 0, // 不用于写
'read' => 1,
));
## 故障转移
### 手动提升Slave为Master
# 1. 在Slave上停止复制
docker exec -it mysql-slave mysql -uroot -pslave_root_pass \
-e "STOP SLAVE;"
# 2. 将Slave设为可写
docker exec -it mysql-slave mysql -uroot -pslave_root_pass \
-e "SET GLOBAL read_only = OFF;"
# 3. 修改应用配置指向新Master
# 修改 wp-config.php 的 DB_HOST
### 使用Orchestrator(自动化)
# docker-compose.yml 添加orchestrator
orchestrator:
image: openarkdb/orchestrator:latest
container_name: orchestrator
ports:
- "3000:3000"
command: >
--config=/etc/orchestrator.conf.json
volumes:
- ./orchestrator.conf.json:/etc/orchestrator.conf.json
networks:
- mysql-replication
## 监控复制状态
### 监控脚本
#!/bin/bash
# check-replication.sh
CONTAINER="mysql-slave"
THRESHOLD=60 # 延迟阈值(秒)
delay=$(docker exec $CONTAINER mysql -uroot -pslave_root_pass \
-e "SHOW SLAVE STATUS\G" | grep "Seconds_Behind_Master" | awk '{print $2}')
if [ "$delay" == "NULL" ] || [ "$delay" -gt "$THRESHOLD" ]; then
echo "告警:复制延迟 ${delay} 秒!"
# 发送告警(邮件/微信/钉钉)
fi
### 添加到Cron
# 每5分钟检查一次
*/5 * * * * /scripts/check-replication.sh
## 备份策略
# 在Slave上备份(不影Master性能)
docker exec mysql-slave mysqldump \
-uroot -pslave_root_pass \
--single-transaction \
--routines \
--triggers \
--all-databases > backup_$(date +%Y%m%d).sql
# 压缩备份
gzip backup_*.sql
## 常见问题
| 问题 | 原因 | 解决方案 |
|------|------|----------|
| Slave_IO_Running=No | 网络问题/密码错误 | 检查MASTER_HOST/PASSWORD |
| Slave_SQL_Running=No | 数据冲突 | SET GLOBAL sql_slave_skip_counter=1 |
| 延迟持续增大 | Slave性能差 | 增加slave_parallel_workers |
| 主从数据不一致 | 误操作 | 重新全量同步 |
## 性能优化
# Master优化(my.cnf)
innodb_flush_log_at_trx_commit = 2 # 提高写性能
sync_binlog = 0 # 由操作系统刷盘
# Slave优化(my.cnf)
innodb_flush_log_at_trx_commit = 2
sync_binlog = 0
slave_parallel_workers = 8 # 并行复制线程数
使用Docker Compose部署MySQL主从复制,可以快速搭建高可用数据库集群,提升WordPress的读取性能。

评论(0)