1. 双机热备份到底在解决什么问题
双机热备份这套东西,说白了就一句话:让两台机器互相盯着,一台倒了另一台立刻顶上,业务方基本感觉不到。我最早接触这个概念是在一套内部业务系统上,那会儿整套服务跑在一台物理机上,硬盘一坏,整个部门停摆一天半。后来做高可用方案做得多了,越来越觉得双机热备份的价值不在于技术多复杂,而在于它把“不可控的停机”压缩成了“可控的几十秒”。它适合谁看?正在从单机往集群过渡的运维、需要给业务承诺可用性指标的后端开发、以及被“机器挂了怎么办”这个问题反复问到的技术负责人。下面我按自己踩过的坑,把这套东西从原理到落地完整捋一遍。
1.1 从一次凌晨的告警说起
某公司的订单处理服务部署在一台独立服务器上,配置不低,跑得也稳,稳定到没人再去看它。某天凌晨两点多,机房那边一块系统盘寿命到了,机器直接失联。值班的人被电话叫醒,先排查是不是网络问题,再确认是不是系统崩溃,最后定位到磁盘故障,换盘、重装、恢复配置、导回数据,天亮之前勉强跑起来,中间空了将近四个小时。
事后复盘,真正的问题不是磁盘坏了——硬件总会坏——而是整套系统里存在一个单点,这个点一断,没有任何东西能接上。而双机热备份要干的事,就是把这个单点变成两个点,并且让“接上”这个动作由机器自动完成,不依赖人在半夜爬起来。这两件事看起来简单,但落地时会牵扯到心跳怎么判、数据怎么保、切换后客户端怎么找到新机器,每一个环节都能卡住人。
1.2 单机架构的三层脆弱点
我习惯把单机的脆弱性拆成三层看,这样设计高可用方案时不容易漏。
硬件层:磁盘、电源、网卡、内存条,任何一样出问题都可能让机器直接不可用。这一层的特点是故障突然、不可预测,但概率相对低,而且往往可以通过冗余硬件缓解一部分。系统层:内核崩溃、文件系统损坏、误操作导致的配置破坏、系统更新后起不来。这一层比硬件层常见得多,尤其在有人频繁登录的机器上。应用层:进程还在但已经卡死、连接池耗尽、死锁、内存泄漏导致响应超时。这一层最麻烦,因为从操作系统的角度看机器完全健康,只是应用不干活了。
对应的检测手段也不一样。硬件和系统层挂了,通常表现为网络不通、心跳中断;应用层挂了,心跳可能还是通的,必须靠主动发起业务探测才能发现。很多双机热备份方案上线后“看着正常,出事不切”,八成就是把应用层故障当成了健康状态,因为检测只做到 ping 通为止,这是最典型的误区。
1.3 热备、温备、冷备、双活:先把概念掰清楚
这几个词在项目会上经常被混着用,导致方案评审时各说各话。我自己整理了一张对照表,谈需求时直接摆出来对齐。
| 形态 | 备用节点状态 | 切换耗时量级 | 数据新鲜度 | 成本 |
|---|---|---|---|---|
| 冷备 | 关机或未部署 | 分钟到小时级 | 依赖备份恢复,可能丢失较长时间数据 | 最低 |
| 温备 | 开机、已装软件,未接管业务 | 分钟级 | 依赖定期同步 | 低 |
| 热备(主备) | 开机、配置对齐、实时待命 | 秒级到十几秒 | 与主节点基本同步 | 中 |
| 双活 | 两个节点同时承载业务 | 接近零 | 需双向同步 | 高,复杂度最高 |
关键差异在“备用节点是否处于随时可接管的状态”。冷备其实只是备份,算不上高可用;温备比冷备强一点,但切换还得人工介入;热备才是真正意义上的自动接管。至于双活,很多团队一上来就想做双活,觉得两边都能跑更划算,实际做下来会发现数据双向同步的一致性、连接路由、故障时的流量再分配,每一项都能把工期拉长好几倍。中小规模的业务系统,主备模式的成功率和性价比远高于双活,这是我做了多个项目之后比较确定的判断。
2. 核心机制拆解:心跳、漂移、仲裁
双机热备份听起来像是一个功能,实际是四五个机制咬合在一起:检测、决策、接管、隔离。任何一个环节设计得粗糙,整套方案就会在关键时刻掉链子。这一章把这几个机制逐个拆开讲,讲清楚“为什么这么设计”,比记住配置模板重要得多。
2.1 心跳检测:怎么判断“它真的死了”
心跳的本质是周期性通信:A 每隔一段时间给 B 发一个信号,B 收到就认为 A 还活着;连续若干个周期没收到,就判定 A 失联。这里有三个参数必须想清楚——间隔、超时、判定次数。
间隔太短,网络轻微抖动就触发误判;间隔太长,真正故障时发现得晚。我一般把间隔设在 1 到 2 秒,判定次数设 3 次,这样最坏情况下大约 3 到 6 秒能发现异常,同时能容忍短暂的网络拥塞。如果业务对切换时间要求更苛刻,可以压到 500 毫秒间隔,但必须配合独立的心跳链路,否则主业务流量一高,心跳包被挤掉,反而更容易误切。
检测方式也分层。最基础的是网络层探测,成本最低但信息最少;往上是传输层端口探测,能确认服务进程是否还在监听;最贴近真实的是应用层探测,比如发一个只读的业务请求,看返回是否符合预期。层次越高越准,开销也越大。我的常规做法是心跳链路用轻量探测保证响应快,同时用应用层脚本做辅助检查,两者都通过才算健康,这样既不拖慢判定速度,又能识别进程假死。
注意:心跳包和业务流量走同一条网线是很多事故的源头。业务流量打满带宽时,心跳包延迟飙升,主节点明明活得好好的,备用节点却判定它死了,直接发起接管。心跳链路单独走一根直连网线或独立交换端口,这不是讲究,是必需。
2.2 虚拟服务地址漂移:客户端为什么感觉不到
光把备用机启动起来没用,客户端连的还是原来那个地址,它不会自己改配置。解决办法是引入一个虚拟服务地址(业内常说的 VIP):这个地址不属于任何一台物理机,平时绑在主节点上,主节点挂了就漂到备用节点上。对客户端来说,它连的永远是同一个地址,后面谁在扛它并不关心。
漂移的实现靠地址声明。备用节点接管时会向外发一个地址解析通告,告诉同一网段内的交换机和主机“这个地址现在在我这儿”,各设备的地址缓存随之更新,后续流量就送到新节点了。这个过程通常在毫秒到秒级完成,所以从客户端视角看,最多是一次连接超时重试。
这里有个容易被忽略的细节:已经建立的连接是救不回来的。地址漂移只保证新连接能找到新节点,老的 TCP 连接因为对端状态已丢失,必然断。所以对短连接的业务(HTTP 接口调用)基本无感,对长连接的业务(数据库连接池、消息订阅、WebSocket)就必须在客户端侧加断线重连逻辑,否则切换完成后业务照样报错。我见过不止一个项目,切换验证时用 curl 测通了就宣称成功,实际上线后应用连接池全挂,用户端一片报错。
2.3 共享存储与数据同步:切换之后数据得对得上
服务能接管只是第一步,数据得跟着走。常见有三条路。
共享存储:两台机器挂同一块存储设备,数据只有一份,谁接管谁读写。好处是绝对不会出现数据不一致,坏处是存储本身又成了一个单点,而且同一时刻必须保证只有一台在挂载使用,否则文件系统会被写坏——这就需要靠隔离机制来保证。块级复制:主节点写本地盘的同时把数据块同步到备用节点,两边各有一份完整数据。这种方式对应用完全透明,但同步是有延迟的,极端情况下会丢最后一点写入。应用层复制:数据库主从、缓存集群这类方案自己在应用层做同步,控制粒度最细,但配置和维护成本也最高。
选哪条路取决于业务对数据丢失的容忍度。订单、账务这类业务,我倾向于用应用层半同步复制,宁可牺牲一点写入性能也要保证提交成功的数据不丢;日志、缓存、会话这类可以重建的数据,块级异步复制就够了,丢了重新生成即可。把不同重要性的数据塞进同一套复制方案,是最常见的过度设计或者设计不足。
2.4 脑裂:最危险的那种“看起来正常”
脑裂指的是两台机器互相认为对方挂了,于是同时以主节点身份接管服务。这种情况特别阴险,因为从监控上看两台机器都活着、服务都在跑,但共享存储被两个进程同时写,数据很快就会出现结构性损坏,事后恢复极其困难。
产生原因通常是心跳链路断了,但两台机器本身都健康。比如心跳网线被拔、心跳交换机重启、或者心跳走的那条链路出现了单向丢包。这时候双方都收不到对方的消息,都判定对方已死,于是都发起接管。
防御手段有三个层次。第一层是增加心跳路径,比如一根直连网线加一条业务网段上的链路,两条路径都断才判定失联,误判概率大幅下降。第二层是仲裁,引入第三台机器作为见证者,任何一方要接管必须先拿到仲裁授权,两边同时申请时只有一方能拿到。第三层是隔离,接管前先把对方强制断电或断网,确保它绝对无法再访问共享资源,这个动作业内叫 fencing 或 STONITH,听起来暴力,但在共享存储场景下是最可靠的兜底。
提示:只用两台机器、没有第三方的方案,在网络分区的情况下理论上无法从根上避免脑裂。如果业务不允许数据损坏,就老老实实加一台仲裁节点,成本不高,能省掉大量事后扯皮。
3. 方案选型与参数计算
方案不是越贵越好,得跟业务的实际损失挂钩。这一章讲怎么根据停机代价倒推架构规模,以及几个必须提前算清楚的参数。
3.1 三种常见拓扑的适用边界
我经手过的双机方案基本落在三种拓扑里,各有明确的适用场景。
| 拓扑 | 节点数 | 优点 | 短板 | 典型适用场景 |
|---|---|---|---|---|
| 纯主备 | 2 | 结构简单,故障边界清晰,排障容易 | 备用节点平时空转,资源利用率低 | 中小规模核心业务、内部管理系统 |
| 主备加仲裁 | 3 | 能有效防脑裂,决策有第三方背书 | 多一台机器的运维成本 | 涉及共享存储、数据强一致的场景 |
| 双主互备 | 2 | 资源利用率高,两边都承载流量 | 需要处理流量分配与冲突,切换逻辑复杂 | 无状态服务、读多写少的接入层 |
对大多数团队来说,主备加仲裁是性价比最高的选择。纯主备适合确定不会用共享存储的场景,比如两边各存一份数据、靠应用层同步。双主互备我只建议用在无状态服务上,一旦涉及写数据,冲突处理能把人逼疯。
3.2 用停机代价倒推 RTO 和 RPO
两个必须量化的指标:RTO(恢复时间目标,业务中断多久必须恢复)和RPO(恢复点目标,最多能接受丢失多长时间的数据)。
算法很简单,先算停机成本。假设某业务每小时营收 6 万,停机一小时直接损失 6 万,加上客户流失和口碑影响,按 2 倍算就是 12 万。如果每天业务高峰期只集中在 4 个小时,那么一年的高风险时段是 1460 小时。把方案成本摊进去:一套能实现 30 秒切换、零数据丢失的架构,年成本 3 万;一套只能做到 10 分钟切换、可能丢 5 分钟数据的架构,年成本 1 万。按故障率每年 2 次估算,前者的期望损失是 2 × 30 秒对应的营收损失,约 1000 元,总支出 3.1 万;后者期望损失约 2 × 5 分钟损失再加上可能的数据修复成本,总支出容易被低估的“事后修复”拉高。
真正决定选型的往往不是这个算术,而是 RPO。如果丢 5 分钟订单数据意味着要人工对账两天,那省下的 2 万块完全不值。RTO 决定切换自动化做到什么程度,RPO 决定数据同步用同步还是异步,这两个问题想明白了,架构基本就定了。
3.3 心跳链路与网络规划
网络规划这块,我总结了几条硬性要求,每次做方案都拿出来对照。
- 心跳走独立物理链路,直连或独立交换端口,不与业务流量共享带宽
- 两台机器的心跳网卡配置在同一网段,避免路由依赖
- 虚拟服务地址与业务地址在同一网段,避免跨网段漂移带来的网关配置问题
- 主备两台的网卡型号、速率尽量一致,混用不同速率的网卡偶尔会出现地址宣告异常
- 交换机端口关闭生成树相关的收敛延迟,或者直接配置边缘端口,减少漂移时的等待
延迟阈值要实测。我通常会在业务流量最高的时段跑一次心跳延迟统计,如果峰值延迟超过心跳间隔的一半,就需要调整参数或者优化链路。这个动作很枯燥,但能提前发现一大批“平时没事、高峰期乱切”的隐患。
3.4 一份可用的核心配置
下面这份配置是我在多个项目里用过的骨架,主备两台机器只有优先级和初始状态不同。
# 全局段 global_defs { router_id node_a # 两台机器必须不同 enable_script_security # 允许执行外部检查脚本 script_user root } # 健康检查脚本定义 vrrp_script chk_biz { script "/etc/ha/check_biz.sh" # 返回 0 表示健康,非 0 表示异常 interval 2 # 每 2 秒执行一次 timeout 3 # 单次执行超时 fall 3 # 连续失败 3 次判定为异常 rise 2 # 连续成功 2 次恢复为健康 weight -40 # 检查失败时优先级降低的量 } # 实例段 vrrp_instance VI_1 { state BACKUP # 两台都写 BACKUP,靠优先级决定角色 interface eth1 # 绑定的网卡 virtual_router_id 51 # 两台必须一致 priority 100 # 主节点 100,备用节点 90 advert_int 1 # 通告间隔 1 秒 nopreempt # 切换后不自动抢占,避免来回抖 authentication { auth_type PASS auth_pass xxxx } virtual_ipaddress { 10.0.0.100/24 } track_script { chk_biz } }几个参数值得展开说。两台都写 BACKUP 是刻意为之:如果主节点写 MASTER、备用写 BACKUP,主节点重启后会立刻抢回地址,如果它当时状态还没恢复好,就会造成二次中断。都写 BACKUP 加优先级比较,谁健康谁上,行为更可控。nopreempt 关闭抢占也是同理,让切换单向发生,等人工确认原主节点完全恢复后再决定是否切回。weight 的负值要大于两台机器的优先级差,这样检查失败时优先级会掉到对方之下,才能真正触发转移;如果两台优先级差是 10、weight 只写 -5,检查失败也不会切换,这是那种“配置看起来没问题但就是不生效”的典型原因。
4. 完整搭建过程记录
这一章按我实际操作的顺序走一遍,从环境检查到切换演练。环境以两台 Linux 服务器为例,一个内网业务系统,前面挂一台反向代理。
4.1 环境规划与前置检查
先把地址规划定下来,别一边配一边改。主节点 10.0.0.11,备用节点 10.0.0.12,虚拟服务地址 10.0.0.100,心跳走 eth1 直连,业务走 eth0。系统版本、内核参数、软件包版本两台必须完全一致,我吃过一次亏:两边内核小版本不同,某个网络参数默认值不一样,导致地址宣告行为有差异,切换后有几秒钟业务不通,排查了一整晚。
前置检查清单如下:
- 两台机器时间同步,偏差控制在 1 秒内,否则日志对不上,排障时会怀疑人生
- 关闭防火墙对心跳协议的拦截,或者精确放行组播与单播流量
- 确认业务端口在两台机器上监听配置一致,尤其是绑定地址,不能写死成物理地址
- 确认应用启动脚本幂等,重复执行不会产生副作用
- 确认日志目录、临时目录、上传目录的路径与权限一致
第 3 条是我认为最容易翻车的地方。很多应用默认绑定到具体物理地址,地址漂移过来之后服务起不来,因为那个地址在备用机上并不存在。必须改成绑定 0.0.0.0 或者绑定虚拟地址。
4.2 安装与角色初始化
软件安装本身没什么可说的,包管理器一条命令。真正需要花时间的是角色初始化的一致性,我通常用一个简单的校验脚本来做。
#!/bin/bash # 两台机器分别执行,输出对比 echo "== 主机名与地址 ==" hostname ip -4 addr show | grep inet echo "== 关键服务状态 ==" systemctl is-enabled app-service systemctl is-active app-service echo "== 目录权限 ==" ls -ld /data/app /data/log /data/upload echo "== 配置文件校验和 ==" find /etc/app -type f -name "*.conf" -exec md5sum {} \;最后一行最关键。配置文件的校验和如果两边不一致,切换过去很可能起不来,或者起来后行为异常。我一般会在每次变更后重新跑一遍这个脚本,把输出存档对比,形成习惯之后,配置漂移这类问题基本绝迹。
初始化时还要处理一个顺序问题:先让备用节点进入待命状态,再启动主节点的业务。反过来操作的话,主节点已经在跑业务,备用节点加入时可能触发一次不必要的状态同步或者抢占,运气不好会造成短暂中断。
4.3 健康检查脚本的三个坑
检查脚本是整套方案里最需要打磨的部分,写得好坏直接决定“该切的时候切不切、不该切的时候乱不乱切”。下面这个版本是我反复改出来的。
#!/bin/bash # /etc/ha/check_biz.sh # 返回 0 = 健康,非 0 = 异常 # 坑一:限制执行时间,防止脚本自己卡死 exec timeout 2 bash -c ' # 坑二:检查进程存在还不够,要检查端口 if ! pgrep -f "app-service" > /dev/null; then exit 1 fi # 坑三:用业务接口验证真实可用性,而不是只看端口监听 resp=$(curl -s -m 2 -o /dev/null -w "%{http_code}" http://127.0.0.1:8080/health 2>/dev/null) if [ "$resp" != "200" ]; then exit 2 fi exit 0 '坑一是超时控制。检查脚本自己卡住的情况不罕见,比如它去请求一个已经半死的接口,TCP 连接建立了但一直不返回,脚本就挂在那里。外层判断拿不到结果,行为就不可预测了。加timeout是必须的。
坑二是进程探测的假阳性。进程在、端口在,但线程池满了、数据库连接断了,业务实际不可用。所以必须往应用层探。这里探本机回环地址而不是虚拟地址,是为了避免地址漂移过程中的干扰。
坑三是返回值的约定。脚本返回非 0 都算异常,但不同返回值可以在日志里区分原因,排障时很有用。我一般约定 1 表示进程没了、2 表示接口异常、3 表示资源告警,日志里一眼能看出问题性质。
注意:检查脚本里千万别做重启服务的动作。有过这样的设计——检查失败就尝试重启一次应用——结果在真正故障时脚本反复重启、反复失败,把切换判定搅得一团乱。检查和修复要分开,检查脚本只负责如实报告。
4.4 切换演练:怎么验证它真的能用
配置完不演练,等于没配。而且演练不能只演“正常切换”,得把各种故障形态都过一遍。
| 演练项 | 操作方法 | 观察重点 | 预期结果 |
|---|---|---|---|
| 进程被杀 | 主节点上强杀业务进程 | 检测延迟、切换耗时 | 数秒内备用接管,业务恢复 |
| 应用假死 | 主节点上阻塞业务接口 | 是否被识别为异常 | 检查脚本返回非 0,触发切换 |
| 整机断电 | 主节点直接断电 | 地址漂移是否干净 | 备用接管,无残留地址 |
| 网络隔离 | 拔掉主节点业务网线 | 是否发生脑裂 | 仲裁生效,仅一方接管 |
| 恢复回切 | 原主节点恢复上线 | 是否发生抢占 | 保持现状,需人工确认 |
每次演练我都要求记录三个数据:检测耗时(从故障发生到判定异常)、切换耗时(从判定异常到备用节点开始服务)、业务恢复耗时(从切换完成到业务请求正常返回)。第三个数字才是业务方真正关心的,前两个是给技术人员定位瓶颈用的。曾经有个项目前两个数字都很漂亮,加起来不到 5 秒,但业务恢复要 40 秒,最后查出来是应用启动时要预热缓存,这个只能靠优化启动流程解决,跟高可用方案本身无关。如果只盯着切换耗时,这个瓶颈永远发现不了。
5. 常见问题与排查实录
方案上线只是开始,真正的功课在后面。这一章是这些年处理过的典型问题,按出现频率排序。
5.1 故障发生了但没切换:原因速查
这是最高频的问题,我整理了一张速查表,按排查顺序排列。
| 现象 | 可能原因 | 排查手段 |
|---|---|---|
| 完全没反应 | 检查脚本未生效 | 手动执行脚本看返回码 |
| 完全没反应 | weight 负值小于优先级差 | 对比两台优先级配置 |
| 有日志但不转移 | 虚拟路由器标识不一致 | 核对两侧实例配置 |
| 有日志但不转移 | 认证密码不一致 | 核对认证段 |
| 转移后立刻回切 | 未关闭抢占 | 开启不抢占选项 |
| 转移后业务不通 | 应用绑定物理地址 | 检查监听地址配置 |
| 转移后业务不通 | 地址宣告未生效 | 在同网段机器上查地址缓存 |
第三条和第四条我遇到过好几次。配置是从模板复制的,模板里有两处需要按实例改,改了一处忘了另一处,结果两边对不上,日志里只有很隐晦的提示,不细看看不出来。后来我养成习惯,配置完成后先把两边配置逐行 diff 一遍,把不该相同的项列出来单独核对。
5.2 来回抖动:切换两次就乱了
有一类故障特别折腾人:主节点故障切到备用,过一会儿又切回来,然后再切过去,循环往复。业务时断时续,比彻底宕机还难受。
原因通常是检查条件处于临界状态。比如主节点 CPU 负载很高,业务接口响应时间在 2 秒上下浮动,检查脚本的超时设的也是 2 秒,一会儿成功一会儿失败,状态来回跳。解决办法有两个方向:一是放宽判定条件,把连续失败次数从 3 提到 5,把超时从 2 秒放到 3 秒,容忍偶发抖动;二是从根上解决,把那个响应慢的接口优化掉。
还有一个原因是没有关闭抢占。主节点短暂异常被接管,恢复后发现自己优先级更高,立刻抢回来;抢回来之后状态还没稳住,又被判定异常……这种反复切换对数据一致性的破坏比单纯宕机大得多。我的做法是:切换必须发生,回切必须人工。自动化只做单向,方向由人来定。
5.3 数据库场景的特殊坑
带数据库的双机方案,坑比无状态服务多一个数量级。
半同步退化成异步。数据库主从配置了半同步复制,看起来是强一致的,但主节点在某个时刻因为超时自动降级成异步,之后所有写入都不同步了,而且日志里只有一行不起眼的提示。等主节点挂了才发现备用节点缺了一大段数据。对策是把这个降级状态纳入监控,一旦发生立刻告警,同时定期比对两边的数据位点差异。
自增主键冲突。双主模式下如果两边都用自增主键,切换后可能出现主键冲突导致写入失败。常规做法是给两边的自增步长和起始值错开,比如一边从 1 开始步长 2,另一边从 2 开始步长 2,互不重叠。
未提交事务的处理。主节点在切换瞬间可能有正在执行的事务,这些事务在备用节点上是完全不知道的。切换后业务重试,可能出现重复下单这类问题。这需要在业务侧做幂等设计,高可用方案本身解决不了。
回切时的数据补偿。原主节点恢复后,它上面可能有切换前没同步出去的数据。直接把它挂回去当从库,这部分数据要么被覆盖丢失,要么造成主键冲突。标准流程是先把它上面的增量数据人工核对导出,确认无冲突后再重新加入集群。这个流程一定要写进运维手册,临时想是想不出来的。
5.4 上线后的日常巡检
方案跑起来之后,最怕的是“逐渐失效”:某次变更改了配置、某次升级换了网卡、某次搬迁挪了链路,方案还在,但已经不能用了,直到真出事才发现。
我保留了一份巡检清单,每周执行一次,十几分钟的事:
- 两台机器的检查脚本各自手动执行一次,确认返回 0
- 查看切换日志,确认没有异常的历史切换记录
- 核对两边关键配置文件的校验和是否一致
- 检查心跳链路的丢包率和延迟,与基线对比
- 确认当前主节点身份符合预期,没有被意外抢占
- 检查数据同步状态,确认延迟在阈值内
- 抽查一次应用层接口,确认服务真实可用
第 3 条和第 5 条最容易被跳过,也最容易出问题。配置漂移是慢性病,平时没症状,出事时致命。至于演练,我建议至少每季度做一次完整切换,规模大的系统可以按季度轮换不同的故障场景,一年下来把主要故障形态都覆盖一遍。
6. 我个人的几点体会
做这套东西这些年,技术上的细节都能查文档,真正难的是几个判断。
一是别把高可用当成万能药。它能解决机器故障,解决不了代码 bug、解决不了数据库慢查询、解决不了业务逻辑错误。有些团队把系统稳定性问题全指望在双机方案上,结果方案上线后故障率一点没降,因为真正的故障源在应用层,跟机器是不是双份没关系。
二是切换时间不要追求极限。见过有人为了把切换压到 1 秒内,把心跳间隔设成 200 毫秒、判定次数设成 1 次,结果网络稍微抖一下业务就切一次,稳定性反而更差。我现在的偏好是检测 5 秒左右、切换 10 秒以内,这个量级对绝大多数业务都够用,而且误判极少。
三是一定要有降级预案。高可用方案本身也可能失效——仲裁节点同时挂了、两台机器同时出问题、切换后新节点起不来。这时候需要有人工介入的兜底流程,包括怎么快速把服务起在备用机上、怎么回滚、数据怎么核对。这套流程写在纸上没用,得实际演练过。
最后分享一个小习惯:每次切换发生后,不管成功还是失败,我都会把当时的监控曲线、日志片段、操作时间线整理成一份复盘文档。攒了几年之后,这份文档库比任何方案文档都有价值,因为里面全是真实发生过的故障形态和处置过程。新同事来了先看这个,比讲一小时原理管用得多。