一主三从 MySQL + 一主三备 Nginx 高可用切换全解
发布时间:2026/9/1 3:07:31 作者:尧图编辑部 阅读量:1,286

一主三从 MySQL 一主三备 Nginx 高可用切换全解本文串联两个常见的高可用场景并回答两个关键疑问一主三从 MySQL靠MHA / Orchestrator / 云 RDS做自动切换——这三者是什么、自动切换怎么做到一主三备 Nginx keepalived——keepalived 是什么、起什么作用、怎么配置和工作主挂 → VIP 漂给其中一台备、其余备继续待命这个 VIP 漂移到底是怎么实现的最后一节专门回答一个跨机房疑问2 主 2 备时一个机房故障、备机接管了流量是不是不用切到另一个机房基础的 keepalived/VRRP 原理见同目录 [[keepalived-VIP高可用原理与三个疑问解答]]本文不再重复只讲进阶与多节点场景。一、一主三从 MySQL 的自动切换MHA / Orchestrator / 云 RDS1. 先说清楚一主三从拓扑┌── slave1 master ───────┼── slave2 ├── slave3 └── ... (一主多从)一主唯一的可写节点 master所有写都打到它。三从通过主从复制binlog relay log从 master 同步数据只读。风险master 挂了整个集群就不能写了。需要一个自动选新主、重建复制拓扑、把流量切过去的机制——这就是 MHA / Orchestrator / 云 RDS 干的事。关键点自动切换 三件事①故障检测 → ②选主 补数据 重建拓扑 → ③流量切到新主。三个产品用的是不同实现但都逃不出这三步。2. MHAMaster High Availability是什么MySQL 早期最经典的高可用切换方案由日本 DeNA 公司的 MySQL 专家山下宏Yoshinori Matsunobu用 Perl 编写2010~2014 年活跃之后基本停更。是老一代HA 的代表。组成MHA Manager独立部署的管理节点负责监控、决策、执行 failover。一台 Manager 可以管多个 MySQL 集群。MHA Node装在每一台 MySQL含 master 和所有 slave上的代理failover 时被 Manager 调用负责读写 binlog、对比 relay log、应用差异日志。工作原理failover 全过程监控Manager 每隔几秒 ping 一次 mastermysqladmin ping 复制健康检查。故障判定连续 N 次连不上 → 判定 master 宕机。收集差异 binlogManager 连上所有 slave从每台 slave 读取它们已收到的最新 binlog 位点对比出谁的数据最新、谁还差哪些 binlog 没应用。选主默认选数据最新的 slave 当新 master也可在配置里指定候选优先级。补数据把新 master 之外的 slave 比新 master 多出来的 binlog先补到新 master 上再把新 master 比其他 slave 多出来的 binlog应用到其他 slave——核心目的是尽量不丢数据。提升 重建拓扑新 master 停掉只读、设为可写其余 slaveCHANGE MASTER TO指向新 master复制恢复。流量切换MHA 本身只管数据库层流量切换要靠外部——常见做法是 MHA failover 完成后触发脚本去改 ProxySQL / VIP / DNS把写流量指到新 master。优点尽量减少数据丢失差异 binlog 补齐机制是 MHA 的灵魂纯软件、不依赖共享存储。缺点已停更多年对 MySQL 8.0 支持弱、GTID 支持不完善需自行打补丁。Perl 依赖、配置繁琐、Manager 自身是单点要再给 Manager 做高可用。不支持原地恢复原 master等更复杂拓扑操作。3. Orchestrator是什么GitHub 开源、用 Go 编写的 MySQL 复制拓扑管理与高可用工具。是 MHA 的现代继任者活跃维护社区主流。核心特点拓扑自动发现连进 MySQL 读SHOW SLAVE STATUS等自动画出主从拓扑图持久化到后端 DBMySQL/SQLite。Web UI JSON API可视化看到整个复制树鼠标点一下就能做提升某台为主移动子树等操作。复杂拓扑支持不仅主从还支持级联复制链式、双主、多源能做拓扑重构move/relocate replica。自动 failover内置故障检测和恢复规则支持候选主优先级、忽略节点、跨机房亲和性等约束。Pseudo-GTID即使没有开 GTID、binlog 位点对不齐也能靠伪 GTID做安全的拓扑重构。流量切换集成原生支持 failover 后调用钩子去操作ProxySQL / HAProxy / VIP / Consul / DNS把流量引到新主。工作原理自动 failover探测Orchestrator 持续探测所有节点连接 复制状态结果写入后端 DB。故障检测连续探测失败 复制断开 → 进入recovery流程。为防脑裂可用orchestrator 仲裁节点quorum或共享后端 DB 锁来保证同一时刻只有一个 failover 在跑。选主按规则选 candidate——数据最新、不在黑名单、符合同机房优先等约束。提升 重建拓扑把候选提升为新主其余 slave 重新挂到新主下复制恢复。钩子切换流量触发 post-failover hook更新 ProxySQL 的后端 / 漂 VIP / 改 DNS让业务感知到新主。优点活跃维护、Go 单文件部署、UI 强大、拓扑操作丰富、和 ProxySQL 等生态集成好。缺点本身要保证高可用后端 DB orchestrator 多实例 raft架构比 MHA 复杂规则多、学习曲线陡。4. 云 RDS阿里云/腾讯云/AWS RDS是什么完全托管的高可用 MySQL——你只管用看不到底层 binlog/复制细节高可用由云厂商兜底。典型实现不公开但业界通行做法主备 共享存储 / DRBD / 存储级复制主和备在底层共享同一份数据或存储层实时复制故障切换时备直接挂载已有数据几乎不丢数据。半同步复制主写 binlog 至少有一个备确认收到才返回降低丢数据概率。切换由云控制面托管监控到主不可用 → 仲裁 → 备提升为主 →DNS/VIP 自动指向新主业务连接短暂中断后自动重连即可。优点零运维、切换秒级、有 SLA 兜底、自带备份/恢复/监控。缺点黑盒、被厂商锁定、跨可用区/跨地域架构受产品形态限制、成本高、定制能力弱。5. 三者对比与自动切换怎么做到的小结维度MHAOrchestrator云 RDS形态自管软件Perl自管软件Go托管服务维护状态基本停更活跃持续迭代故障检测Manager ping探测 后端持久化云控制面监控选主/补数据差异 binlog 补齐拓扑重构 Pseudo-GTID共享存储/半同步切的是挂载点流量切换外部脚本触发内置 hook 调 ProxySQL/VIP/DNSDNS/VIP 自动适合老集群、MySQL 5.x自建、需要复杂拓扑不想自己运维、要 SLA一句话自动切换的通用套路 健康检查 → 仲裁判活防脑裂→ 选数据最新的备 → 提升 重建复制拓扑 → 调钩子把 VIP/ProxySQL/DNS 指到新主。三个产品的差别只是谁来执行这几步、用什么机制补数据、流量切换谁来做。二、一主三备 Nginx keepalived1. keepalived 是什么keepalived是一个跑在 Linux 上的高可用软件核心基于VRRP 协议Virtual Router Redundancy Protocol虚拟路由冗余协议。它本来是给 LVS 负载均衡器做高可用的但因为能管理 VIP 做进程健康检查现在广泛用于Nginx / HAProxy / 任何单点服务的高可用。keepalived 在这个场景里干两件事管理 VIP让 VIP 同一时刻只绑在一台机器的网卡上主挂了自动漂到备。进程健康检查通过vrrp_script定期检查 Nginx 是否活着Nginx 挂了即使机器还活着也触发 VIP 漂移这比机器宕机才漂更精细。VRRP 基础原理MASTER/BACKUP 选举、priority 含义、广播超时漂移见 [[keepalived-VIP高可用原理与三个疑问解答]]。下面只讲一主三备的进阶。2. 一主三备的拓扑外部流量 ── VIP(192.168.1.100) ── 当前 MASTER ┌──────────────┬──────────────┬──────────────┐ Nginx-1 Nginx-2 Nginx-3 Nginx-4 MASTER BACKUP BACKUP BACKUP priority 150 priority 140 priority 130 priority 120 (绑 VIP) (待命) (待命) (待命)四台机器同一个 VRID虚拟路由器 ID组成一个 VRRP 组共用同一个 VIP。同一时刻只有一台是 MASTER绑着 VIP、响应 ARP、收流量其余三台都是 BACKUP不绑 VIP、不收流量只是持续听 MASTER 的广播。priority 拉出阶梯150/140/130/120不是分流比例而是**谁先接班的排队顺序**。3. keepalived 配置示例主Nginx-1priority 150/etc/keepalived/keepalived.conf# 健康检查脚本每 2 秒 curl 一次 Nginx失败则本机 priority 减 20 vrrp_script chk_nginx { script killall -0 nginx || curl -s -o /dev/null http://127.0.0.1/ interval 2 fall 2 rise 2 weight -20 } vrrp_instance VI_1 { state MASTER # 初始状态仅初始实际靠选举 interface eth0 virtual_router_id 51 # 四台必须一致 priority 150 # 主最高 advert_int 1 # 1 秒发一次 VRRP 广播 authentication { # 同组四台要一致 auth_type PASS auth_pass MyPwd123 } virtual_ipaddress { 192.168.1.100 # 对外的 VIP } track_script { chk_nginx # 把 Nginx 健康和 VRRP 状态绑定 } notify_master /etc/keepalived/notify.sh master notify_backup /etc/keepalived/notify.sh backup }备Nginx-2/3/4完全一样只改state BACKUP和priority140/130/120。其余字段VRID、VIP、认证口令、track_script四台必须一致。健康检查脚本的意义没有它只有机器宕机才漂 VIP有了它Nginx 进程挂了但机器还活着也会漂——weight -20让本机 priority 从 150 掉到 130立刻低于其它备份中的某台触发抢占切换。这是应用级高可用的关键。4. keepalived 的工作流程启动四台同时发 VRRP 报文按 priority 比大小Nginx-1150当选 MASTER绑 VIP、对外 ARP。运行MASTER 每 1 秒组播一个 VRRP advert含自己的 priority三台 BACKUP 持续收“主还活着我不动”。健康检查MASTER 上的chk_nginx每 2 秒检查 Nginx。故障若 Nginx-1 整机宕机 → 三台 BACKUP 收不到 advert超时约 3 秒后其中 priority 最高的 Nginx-2140升级为 MASTER绑 VIP、发免费 ARP。若只是 Nginx-1 上的 Nginx 进程挂 →weight -20把它的 priority 拉到 130低于 Nginx-2 的 140Nginx-2 抢占成为 MASTER。恢复Nginx-1 修好、priority 恢复到 150。默认preempt开启会抢回 MASTER可设nopreempt避免来回震荡。5. keepalived 的作用总结能力说明VIP 管理保证 VIP 同一时刻只在一台机器上主挂自动漂到备VRRP 选举priority 决定排队顺序故障时自动选接班人进程健康检查vrrp_script让应用挂也能触发切换不限于机器挂通知钩子notify_master/backup在切换时执行脚本发告警、reload 等负载均衡keepalived 本身还能配 IPVS 规则做 LVS但本场景主要用 VIP 高可用注意keepalived不分流、不做负载均衡。一主三备里同一时刻 VIP 只在 MASTER 上所有流量都打到 MASTER 一台其余三台是纯待命的冷备。想要三台都干活就不能用主备 VIP而要换成前端加 LVS/Nginx 四层 LB 分流见 [[keepalived-VIP高可用原理与三个疑问解答]] 的主主模式一节。三、主挂 → VIP 漂给其中一台备其余继续待命漂移是怎么实现的这是 VRRP 状态机 免费 ARP 共同完成的拆成三步1. 触发BACKUP 收不到 MASTER 的广播MASTER 每秒发一个 VRRP advert组播到224.0.0.18报文里带着 VRID 和自己的 priority。三台 BACKUP 持续监听。当连续3 个 advert_int skew_time默认约 3 秒收不到 advertBACKUP 判定 MASTER 已死。三台 BACKUP 都会同时进入这个判断但谁先升级取决于 prioritypriority 最高的Nginx-2140先发我要当 MASTER的 advert其余两台130/120收到后发现自己 priority 更低就退回 BACKUP 继续待命。所以最终只有一台升级另外两台仍在待命——这正是题目说的漂给其中一台备、其他备继续待命。2. 绑定新 MASTER 把 VIP 绑到自己网卡Nginx-2 升级为 MASTER 后执行ip addr add 192.168.1.100 dev eth0把 VIP 配到自己网卡上。这一步是本地的内核操作VIP 从原 MASTER 网卡上摘下原主已死自然没了、绑到新 MASTER 网卡上。3. 通告发免费 ARPgratuitous ARP刷新网络层这是让外部流量真正漂过来的关键一步。光在本地绑 VIP 没用——上游交换机/路由器的 MAC 地址表里192.168.1.100 → 旧 MASTER 的 MAC还是旧记录包还是会发到旧 MASTER已死丢包。所以新 MASTER 立刻广播一个免费 ARP内容是192.168.1.100 对应的 MAC 是我新 MASTER。交换机收到后刷新 MAC 地址表之后发往 192.168.1.100 的二层帧就走新 MASTER 的端口了。流量这才真正漂过来。①MASTER 挂 → ②BACKUP-2 超时升级 → ③ip addr add VIP → ④发免费 ARP → ⑤交换机刷新 MAC 表 → ⑥流量到新 MASTER一句话VIP 漂移的本质 VRRP 状态切换决定谁来当新主 免费 ARP让网络层把 VIP 的流量引到新主不是路由改道而是二层 MAC 重新映射。4. 为什么其余两台继续待命因为同一时刻只能有一个 MASTER。Nginx-2 升级后会继续每秒发 advertNginx-3/4 收到 advert、看到自己 priority 更低就保持 BACKUP 状态不绑 VIP、不收流量。整个组始终只有一台绑 VIP这是 VRRP 协议保证的和有几台备无关。四、跨机房疑问2 主 2 备一个机房故障、备机接管了流量还要不要切到另一机房你的判断“备机接管了那流量应该不用切到另一个机房吧” ——方向是对的但前提需要分清楚到底是机房故障还是机房内主库故障。关键要把两种故障区分开1. 情况 A机房内主库故障备机还活着不是整个机房挂典型拓扑同机房主备机房Amaster-A slave-A 机房Bmaster-B slave-B A、B 之间可能互为主从做跨机房容灾master-A 挂了但机房 A 本身没断电断网slave-A 还活着。slave-A 提升为新主同机房接管VIP 仍在机房 A 内漂移业务流量仍打在机房 A。结论流量不用切到机房 B。你的理解完全正确——这是机房内故障转移备机就近接管流量原地不动。2. 情况 B整个机房故障断电/断网/火灾机房内全部节点都死这才是题目字面说的机房故障。机房 A 整个挂了 → master-A 和 slave-A都死了slave-A 没法接管。必须跨机房把流量切到机房 B 的 master-B或机房 B 的备提升让机房 B 承担全部流量。结论真正的机房级故障备机根本接管不了它自己也挂了必须切到另一个机房。题目里备机接管了这个前提在机房级故障下不成立。3. 回到你的问题“一个机房故障备机接管了那么流量不需要切到另一个机房吧”如果故障指的是机房内主库挂了、备机同机房还活着能接管 →对流量不切机房原地漂 VIP 即可。如果故障指的是整个机房挂了、机房内所有节点含备机都死 →必须切到另一个机房因为备机也死了、没东西可接管。所以正确的表述应该是故障级别备机能否接管流量是否切机房机房内主库故障能同机房备接管否原地漂 VIP机房级故障整机房挂不能备也挂了是跨机房切到存活机房4. 跨机房切换还要注意的事真正切机房时光数据库切过去不够还要同步处理流量入口切换DNS / 全局 LB / VIP跨机房 VIP 漂移要看二层是否打通往往用 DNS 或上层 LB 更现实把流量引到机房 B。数据一致性跨机房复制有延迟切过去时可能丢未同步的写要靠半同步复制 回退窗口或分布式事务/对账兜底。回切机房 A 恢复后要先把机房 A 的数据从机房 B 同步回来、确认一致后再切回避免回切导致数据回退。一句话总结备机接管发生在机房内还是跨机房取决于备机本身有没有跟着挂。机房内故障→原地接管、流量不动机房级故障→备机也死、必须跨机房切。你不用切机房的直觉准确对应的是前者。五、整张图从数据库到接入层的高可用全貌外部流量 │ ┌─────┴─────┐ │ VIP/LB │ ← keepalived 管 VIP主挂漂到备 └─────┬─────┘ ┌──────────────┼──────────────┐ Nginx-1(主) Nginx-2(备) Nginx-3/4(备) ← 一主多备同时刻只一台绑 VIP │ 应用层 (写打 master) │ ┌─────┴─────┐ │ MySQL HA │ ← MHA/Orchestrator/云RDS 管选主拓扑重建 └─────┬─────┘ ┌──────────────┼──────────────┐ master slave1 slave2/slave3 ← 一主三从主挂选最新备提升 │ (跨机房) master-B slave-B ← 机房级故障时切到存活机房六、三句话回顾全文一主三从 MySQL 自动切换MHA差异 binlog 补齐停更、OrchestratorGo活跃拓扑重构钩子切流量、云 RDS托管共享存储/半同步——都遵循健康检查→仲裁选主→补数据提升→流量切过去四步套路。一主三备 Nginx keepalivedkeepalived 靠 VRRP 让同一时刻只有一台 MASTER 绑 VIPpriority 排队决定接班顺序vrrp_script把 Nginx 进程健康绑进来主挂/Nginx 挂都触发漂移。它不分流三台备是纯待命。VIP 漂移本质VRRP 状态切换选新主 免费 ARP刷新交换机 MAC 表把 VIP 流量引到新主。跨机房疑问机房内主库故障→同机房备接管、流量不动机房级故障→备也死、必须跨机房切。