Docker Compose 本身不提供高可用,MySQL 8.0 主从复制也不等于高可用;必须手动补足主从同步、健康探活与自动切换三层,或引入 Orchestrator 等外部组件,否则无法容忍单点故障。

直接上结论:Docker Compose 本身不提供高可用(HA),它只是编排工具;MySQL 8.0 的主从复制 ≠ 高可用,缺少自动故障转移和脑裂防护。真要快速落地「可容忍单点故障」的 MySQL 8.0,必须手动补足主从 + 健康探活 + 切换逻辑三层,或引入外部组件(如 Orchestrator、MHA、ProxySQL)。下面说清楚每一步怎么做、为什么不能跳过、以及最容易翻车的地方。
docker-compose.yml 必须显式隔离主从容器网络与数据卷
很多人把 master 和 slave 写在一个 docker-compose.yml 里就以为“集群”了,但默认共享网络命名空间会导致端口冲突、server-id 冲突、甚至 binlog 被误读。必须拆开并强制隔离:
- 两个 service 不能共用
volumes段定义,每个必须有独立数据挂载路径,例如/opt/mysql/master/data和/opt/mysql/slave/data - 禁用默认 bridge 网络,显式声明自定义网络:
networks: mysql-ha-net: driver: bridge,并在每个 service 下指定networks: - mysql-ha-net - 主从容器的
container_name必须不同,且不能含下划线(MySQL 内部解析 host 时对下划线敏感) - 从库启动前,主库必须已运行且
SHOW MASTER STATUS可查;建议在 slave 的depends_on中加健康检查条件(见下一条)
depends_on 不等于“等主库 ready”,必须用 healthcheck + custom script
depends_on 只检查容器进程是否 running,不检查 MySQL 进程是否 accept 连接、是否完成初始化、是否开启 binlog。常见错误是 slave 启动后立刻执行 CHANGE REPLICATION SOURCE TO,结果报错 ERROR 2003 (HY000): Can't connect to MySQL server 或 ERROR 3021 (HY000): The requested source log file does not exist。
- 为主库添加
healthcheck,用mysqladmin ping+ 用户密码验证连通性,例如:healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p123456"] interval: 10s timeout: 5s retries: 10
- 从库的
depends_on必须引用主库的 healthcheck,写成:depends_on: mysql-master: condition: service_healthy - 更稳妥的做法:把
CHANGE REPLICATION SOURCE TO和START REPLICA封装进一个 shell 脚本,挂载到 slave 容器内,在容器 entrypoint 中调用,确保只在主库真正 ready 后才执行同步配置
MySQL 8.0 主从必须用 replication user,且密码加密方式要降级
MySQL 8.0 默认用 caching_sha2_password 插件,但旧版客户端(包括部分复制协议栈)不兼容,从库连接主库时会报错:ERROR 2061 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded。
- 主库中创建复制用户时,必须显式指定认证插件:
CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'replpass';
- 赋予权限:
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; FLUSH PRIVILEGES;
- 确认主库 my.cnf 启用了必要参数:
server-id、log-bin、binlog-format=ROW、enforce-gtid-consistency=ON、gtid-mode=ON(GTID 是安全切换前提) - 从库配置中,
SOURCE_AUTO_POSITION=1必须启用,否则基于文件名/位置的 CHANGE 语句极易因 binlog 清理出错
没有自动 failover 就不算高可用,别信“主从能切”这种话
手动 STOP REPLICA; RESET REPLICA ALL; 再把原从库升主、应用日志、改应用连接地址——这套操作在生产环境平均耗时 3~8 分钟,期间写入完全中断。所谓“高可用”要求 RTO
- 最轻量方案:用
pt-heartbeat+ 自定义脚本监控延迟,配合mysqlfailover(MySQL Utilities 已废弃)或现代替代品如orchestrator-client - 更推荐:在 compose 外部署一个
proxy层(如 ProxySQL),它内置健康检查和自动重路由,主挂了自动把流量切到从库(需提前配置mysql_replication_hostgroups) - 注意:ProxySQL 本身也要高可用,至少双实例 + keepalived VIP,否则它成了新单点
- 真正省心的路子是跳过 Docker Compose,直接上云厂商托管服务(如 AWS RDS MySQL Multi-AZ、阿里云 PolarDB),它们底层已封装 GTID + 自动故障转移 + 无感 DNS 切换
最后强调一点:MySQL 8.0 的 group_replication 插件虽支持多主自动同步,但它在 Docker 环境下对网络抖动极度敏感,且 require bind-address=0.0.0.0 和稳定的主机名解析——这两点在动态 IP 的容器网络里极难稳定满足。别为了“技术先进”硬上,先跑通主从+ProxySQL,再考虑 MGR。


















