搭建MySQL高可用架构时,最怕的不是方案本身复杂,而是没有先想清楚业务到底能容忍多长时间的不可用、能承受多少数据丢失。如果只是简单搭一个主从复制就认为高可用已经完成,往往会在真正的故障中付出代价。主从复制解决的是读写分离和基础冗余,但不会自动把从库提升为主库,也不会处理网络分区带来的脑裂问题。下面从复制基础开始,逐步拆解几种主流高可用方案,并给出可以落地的配置思路。

评估一个高可用方案,通常看三个指标:RPO(恢复点目标,即最多丢多少数据)、RTO(恢复时间目标,即故障后多久恢复)以及运维复杂度。异步复制RPO可能是几十秒甚至几分钟的事务量,半同步复制则能大幅缩短这个窗口;MHA可以把RTO控制在几十秒内;Group Replication依靠多数派协议可以做到更短的切换时间,但代价是网络和配置要求更高。
一、复制架构的取舍:从异步到半同步
MySQL原生复制默认是异步模式,主库提交事务后不会等待从库确认,直接返回客户端成功。这样做性能最好,主库不会因为从库延迟而阻塞写入,但一旦主库崩溃,已经提交但尚未传输到从库的binlog就会丢失。对于订单、支付这类强一致业务,这种丢失可能不可接受。
半同步复制在异步的基础上增加了一个确认步骤:主库在提交事务时,至少等待一个从库把binlog写入到relay log并返回ack,之后才返回客户端成功。通过 rpl_semi_sync_master_enabled 和 rpl_semi_sync_slave_enabled 两个变量可以开启。它的RPO窗口缩小到最后一个未确认的事务,但会增加主库的写入延迟,特别是在从库网络抖动时。
下面是一个开启半同步复制的示例。需要注意插件安装后,主库和从库都需要设置对应的变量,并且从库的复制线程要重新连接才能生效。
-- 主库执行 INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; SET GLOBAL rpl_semi_sync_master_enabled = 1; SET GLOBAL rpl_semi_sync_master_timeout = 1000; -- 从库执行 INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; SET GLOBAL rpl_semi_sync_slave_enabled = 1; STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;
超时时间 rpl_semi_sync_master_timeout 表示主库等待从库确认的毫秒数。如果超过该时间没有收到确认,主库会退化为异步复制,避免写入被无限阻塞。这个机制保证了可用性,但也意味着极端情况下半同步可能退化为异步,所以监控从库状态非常重要。
二、用MHA实现自动故障切换
主从复制加半同步可以降低数据丢失风险,但主库故障后仍需要人工介入把从库提升为主库。MHA(Master High Availability)是一个用Perl编写的自动化故障切换工具,它通过监控主库状态,在检测到主库不可用时自动选择一个最接近原主库数据的从库提升为新的主库,并把其他从库重新指向新主库。
MHA的核心思想是尽量补齐故障主库的binlog。在故障切换前,MHA会尝试从原主库的binlog中获取尚未应用到从库的事件,如果原主库还能通过SSH访问,则直接拉取差异binlog;如果不能访问,则从其他从库的relay log中补齐。这样能够最大限度地减少数据丢失。对于业务来说,故障切换时间通常可以控制在30秒以内。
MHA的配置主要分为两部分:manager节点上的配置文件,以及所有节点之间的SSH免密登录。下面是一个典型的 app1.cnf 配置文件片段,定义了三个MySQL节点和一个管理节点。
[server default] manager_workdir=/var/log/masterha/app1 manager_log=/var/log/masterha/app1/manager.log master_binlog_dir=/var/lib/mysql remote_workdir=/tmp ping_interval=1 secondary_check_script=masterha_secondary_check -s 192.168.10.12 -s 192.168.10.13 master_ip_failover_script=/usr/local/bin/master_ip_failover [server1] hostname=192.168.10.11 candidate_master=1 [server2] hostname=192.168.10.12 candidate_master=1 [server3] hostname=192.168.10.13 no_master=1
其中 candidate_master=1 表示该节点允许被提升为主库,no_master=1 表示该节点永远不参与选主,通常给报表或备份从库使用。MHA的自动故障切换需要配合VIP漂移或者应用层路由更新,因为提升主库后客户端连接地址需要切换到新主库。没有VIP自动切换的环境,即使MHA完成了选主,业务也可能连不上新库。
MHA的优点是成熟稳定、切换逻辑透明,缺点是它主要针对传统异步或半同步复制,不支持多主写入,而且对网络分区场景下的脑裂需要额外处理。如果业务已经有大量的自动化平台,MHA可以作为其中的故障切换组件来使用。
三、MySQL Group Replication与InnoDB Cluster
MySQL Group Replication(MGR)是一种基于Paxos协议的高可用方案,它不依赖传统的异步复制,而是把多个节点组成一个复制组,事务必须在多数派节点上达成一致后才能提交。这样即使少数节点故障,集群仍然可以提供服务,而且不会出现传统主从架构中主库故障后必须手动选主的麻烦。
MGR有两种模式:单主模式和多主模式。单主模式下只有一个节点接受写入,其他节点只读,主节点故障后组内会自动选出新主;多主模式下所有节点都能写入,但需要应用处理冲突检测。生产环境中更推荐单主模式,因为多主写冲突的处理逻辑复杂,并且对网络延迟敏感。
部署MGR需要配置 group_replication_group_name、group_replication_local_address 和 group_replication_group_seeds 等参数。下面是一个节点加入复制组的关键步骤。
-- 创建复制用户 SET SQL_LOG_BIN=0; CREATE USER rpl_user@'%' IDENTIFIED BY 'password'; GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%'; FLUSH PRIVILEGES; SET SQL_LOG_BIN=1; -- 配置恢复通道 CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='password' FOR CHANNEL 'group_replication_recovery'; -- 安装MGR插件 INSTALL PLUGIN group_replication SONAME 'group_replication.so'; -- 第一个节点引导组 SET GLOBAL group_replication_bootstrap_group=ON; START GROUP_REPLICATION; SET GLOBAL group_replication_bootstrap_group=OFF;
只有第一个节点需要设置 group_replication_bootstrap_group=ON,后续节点直接执行 START GROUP_REPLICATION 即可加入组。MGR要求至少三个节点才能保证多数派,两个节点时一个故障就会失去仲裁能力。
在MGR之上,MySQL官方还封装了InnoDB Cluster,通过MySQL Shell可以一键创建集群、添加节点、检查状态。它内部集成了Group Replication、MySQL Router和自动成员管理,适合希望减少手工配置的团队。使用InnoDB Cluster时,一条 dba.createCluster('myCluster') 命令就能完成大部分初始化工作,后续通过 cluster.addInstance() 添加节点。虽然上手简单,但底层原理仍然是MGR,因此网络规划和节点数量要求没有变化。
四、方案对比与常见误区
选择哪种高可用方案,不能只盯着故障切换速度,还要结合团队运维能力和业务特征。下面用一个表格对比三种常见方案的核心差异。
| 方案 | 数据一致性 | 故障切换 | 运维复杂度 | 适用场景 |
|---|---|---|---|---|
| 主从+半同步 | 接近同步,可能退化异步 | 人工或脚本介入 | 低 | 读多写少,容忍秒级丢失 |
| MHA | 异步/半同步,RPO较小 | 自动,约30秒 | 中 | 传统复制架构,需要自动切换 |
| MGR/InnoDB Cluster | 多数派一致,强一致 | 自动,较快 | 中高 | 要求强一致,可接受网络要求 |
第一个常见误区是以为搭建了主从复制就等于高可用。主从复制只解决了数据冗余,没有解决故障后的连接切换和选主逻辑。第二个误区是双主写入可以提升性能,实际上两个节点同时写入时,自增ID、唯一键冲突、事务隔离等问题会让应用层付出更高的复杂度,很多线上事故都源于双主误配。
另一个容易被忽视的是脑裂问题。在MHA或传统主从环境中,如果manager和主库之间网络断开,但主库和业务仍然连通,就可能出现两个节点都认为自己是主库的情况。对MHA而言,需要配置 secondary_check_script 从多个网络路径确认主库状态;对MGR来说,多数派机制天然避免脑裂,但节点数必须为奇数,否则故障时无法形成多数派。
最后,高可用不是搭完就结束了。监控要覆盖主从延迟、半同步状态、故障切换日志、VIP漂移情况等。如果监控缺失,MHA自动切换后可能没有任何告警,等业务报错时才被发现。建议至少对 Seconds_Behind_Master、rpl_semi_sync_master_status、MGR的 group_replication_member_state 做持续采集和告警。