在分布式系统里,MySQL通常作为核心存储承担交易与状态数据。要让多个业务节点共享同一份可信数据,最实用的做法是用主从复制把写操作集中到主库、读操作分散到从库。下面以最常见的三节点结构为例,说明从零开始搭建MySQL环境并配置主从的完整过程。

一、环境规划与容器准备
分布式场景下的MySQL环境不一定非要裸机部署,使用Docker能大幅缩短准备时间。我们规划一个主库和两个从库,它们处于同一自定义网络中,通过容器名互相访问。这种结构既贴近生产中的多实例隔离,也方便在单机做演示。
首先创建专用网络,避免容器暴露在默认网桥中。网络隔离能减少端口冲突,也更符合分布式系统对安全边界的要求。随后拉取官方MySQL镜像,建议固定小版本号,防止自动升级导致配置差异。
# 创建分布式MySQL专用网络 docker network create mysql_dist_net # 拉取指定版本镜像 docker pull mysql:8.0.36
二、主库启动与基础配置
主库需要开启binlog并配置唯一的server-id,这是主从复制的前提。binlog记录所有更改数据的语句或行信息,从库通过读取这些日志重放事务。如果server-id重复,复制链路会直接报错中断。
我们通过挂载配置文件方式启动主库,在配置中指定日志格式为ROW,这种格式能保证从库与主库数据行级一致,尤其在涉及函数或不确定值时比STATEMENT更安全。同时设置expire_logs_days避免日志无限膨胀。
[mysqld] server-id=1 log-bin=mysql-bin binlog_format=ROW expire_logs_days=7 default_authentication_plugin=mysql_native_password
启动主库容器并映射端口,之后进入容器为复制创建专用账号。该账号只需REPLICATION SLAVE权限,不应授予业务库写权限,降低安全风险。
docker run -d --name mysql-master
--network mysql_dist_net
-p 3307:3306
-e MYSQL_ROOT_PASSWORD=rootpass
-v ./master.cnf:/etc/mysql/conf.d/master.cnf
mysql:8.0.36
# 进入容器创建复制账号
docker exec -it mysql-master mysql -uroot -prootpass
-e "CREATE USER 'repl'@'%' IDENTIFIED BY 'replpass';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;"
三、从库配置与主从关联
两个从库分别使用server-id 2和3,并开启relay-log用于存储从主库拉取的binlog。 relay-log 是从库重放的中转文件,合理配置可提升恢复效率。从库不需要开启log-bin,除非打算级联复制。
在关联之前,必须获取主库当前binlog位点。若主库已有数据,应先做一致性备份再记录坐标,否则从库会因缺少历史数据而复制报错。演示环境主库为空,可直接使用SHOW MASTER STATUS获取File与Position。
# 主库查看位点 docker exec -it mysql-master mysql -uroot -prootpass -e "SHOW MASTER STATUS;"
假设返回文件为mysql-bin.000003,位置为157。启动从库后执行CHANGE MASTER命令指向主库,并启动复制线程。下面以从库1为例,从库2仅需修改server-id与容器名。
docker run -d --name mysql-slave1
--network mysql_dist_net
-p 3308:3306
-e MYSQL_ROOT_PASSWORD=rootpass
-v ./slave1.cnf:/etc/mysql/conf.d/slave1.cnf
mysql:8.0.36
docker exec -it mysql-slave1 mysql -uroot -prootpass
-e "CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='repl',
MASTER_PASSWORD='replpass',
MASTER_LOG_FILE='mysql-bin.000003',
MASTER_LOG_POS=157;
START SLAVE;"
四、复制状态验证与常见问题
配置完成后,最重要的步骤是检查从库复制线程是否正常运行。通过SHOW SLAVE STATUS可以观察Slave_IO_Running与Slave_SQL_Running是否均为Yes,以及Seconds_Behind_Master延迟秒数。
如果出现Slave_SQL_Running为No,多半是事务冲突或位点不对。此时可先STOP SLAVE,跳过错误事务再启动,但生产环境应优先修复数据而非盲目跳过。另外,分布式系统常因网络抖动导致IO线程断开,MySQL 8自带自动重连,一般无需人工干预。
docker exec -it mysql-slave1 mysql -uroot -prootpass -e "SHOW SLAVE STATUSG"
| 检查项 | 正常表现 | 异常排查 |
|---|---|---|
| Slave_IO_Running | Yes | 网络不通或账号权限不足 |
| Slave_SQL_Running | Yes | 事务冲突或位点错误 |
| Seconds_Behind_Master | 接近0 | 主库写入峰值过高 |
五、读写分离与分布式接入
环境搭好后,分布式系统的应用层应把写请求发往主库,读请求轮询从库。可借助ProxySQL或ShardingSphere等中间件实现透明路由,避免业务代码硬编码数据库连接。
以ShardingSphere为例,在配置中声明主从逻辑库,框架会自动把SELECT路由到从库,INSERT或UPDATE走主库。这样即使后续扩展从库节点,业务端也无需改动。结合前面容器化部署,整体环境从规划到可用基本能控制在半小时内。
rules:
- !REPLICA_QUERY
dataSources:
primary: mysql-master:3306
replicas:
- mysql-slave1:3306
- mysql-slave2:3306
loadBalancer: round_robin
通过上述步骤,分布式系统中的MySQL主从环境就完成了快速搭建。重点在于提前规划server-id与binlog、准确获取复制位点,以及用自动化工具降低人工操作失误。后续可在此基础上引入半同步复制或MGR,进一步提升数据可靠性。