
先把结论摆出来:多活容灾管的是"谁来接管",脑裂防护管的是"只能有一个说了算"
很多人一听百度斗篷多活容灾,第一反应就是"哦,多部署几套服务呗"。这个理解偏了。它真正要建立的是一套机制——某个可用区出问题的时候,流量能按约定被仲裁、被收敛地接管过去。麻烦在于,只要接管这个决策没有独立的仲裁源兜着,多活部署反而会把原本的单点故障放大成规则版本分叉:两个可用区各按各的本地规则对外服务,跳转策略对不上,出了问题你连哪份配置是准的都判断不了。所以这两件事必须成对设计,一个回答流量往哪走,另一个回答决策权归谁。
当然这个判断有前提。斗篷系统的判定结果是有状态的,规则版本、指纹库、名单数据都得保持一致才行。要是业务本身就允许各区域独立决策、结果有差异也能忍,那多活的复杂度可以砍掉一大截;可只要跳转结果会影响到投放归因和审核表现,仲裁机制就得老老实实纳入设计范围。
概念定义:百度斗篷语境下的多活容灾指什么
说清楚点,百度斗篷多活容灾指的是斗篷的请求接入层、判定引擎、规则配置还有日志链路,在两个或更多可用区同时跑起来。当某个可用区碰上网络中断、实例不可用或者响应超时,流量按预设策略转移到剩下的可用区,而且这个转移过程不能产生规则版本冲突,也不能出现决策结果不一致。它管三个层面:接入层的流量切换、判定层的结果一致性、配置层的数据同步。
这里得跟两个相邻概念划清界限。一个是单可用区内的多副本冗余,那玩意儿只解决实例级故障,可用区级隔离它管不了;另一个是冷备切换,备用区平时不承载流量,切换窗口长、状态同步也滞后。多活容灾要求备用区平时就扛一部分流量、保持状态新鲜,不然接管的时候缓存一片空白、判定跟着抖。
与普通负载均衡的差别
普通负载均衡把请求分给健康实例,它看的是实例活没活;多活容灾看的是可用区整体可用性以及决策权归谁。前者根本不关心两个区的规则版本一不一致,后者非关心不可。斗篷类系统和通用Web服务在多活设计上的主要分歧,就落在这儿。
机制与组成:跨可用区流量接管的四个构件
流量调度层
调度层的活儿是把请求导向当前持有决策权的那个可用区。常见做法是全局流量管理配合健康探测,但探测维度别只盯着端口存活,判定接口的响应时延、规则版本号都得纳入进来。只探端口会漏掉一种中间态——服务活着,可规则加载失败了。这种节点一旦接管流量,错误判定就会扩散到全量请求上,很要命。
规则配置、指纹库、名单数据这些,需要在可用区之间同步。同步方式分两类:强同步保证一致性,代价是判定时延上去了;异步复制时延低,但存在窗口期差异。斗篷判定对时延敏感,多数实现会选异步复制加版本号校验,接管前强制做一次版本对齐。
仲裁与决策权层
这块是脑裂防护的核心所在。仲裁源得是独立于两个可用区的第三方,比如独立的仲裁服务、带租约的分布式锁,或者基于多数派的选主机制。两个可用区不能互相投票决定谁接管——网络一分区,双方都以为对方死了。仲裁源可用不可用,直接决定接管能不能发生;它自己也需要冗余,但绝不能跟被仲裁的可用区共享故障域。
接管发生之后,原可用区恢复时得做状态回补,判定日志、计数类数据、限流令牌都在回补范围内。不做收敛的话,回切时会出现限流额度翻倍、频次统计失真这些次生问题。
脑裂防护:成因、信号与设计要点
脑裂的典型成因
脑裂就是两个可用区同时认为自己持有决策权、同时对外服务。成因有三类。一类是仲裁源与被仲裁节点之间网络分区;一类是健康探测误判,备用区提前接管了,原区却没释放;还有一类是配置同步中断后,两侧各自继续接受变更——这类最隐蔽,表面看两侧规则都能跑,可跳转结果已经开始出现分区域差异了。
可观测的脑裂信号
- 同一时刻两个可用区都在输出判定日志,规则版本号还对不上
- 配置变更在两个区分别生效,变更审计记录出现分叉
- 限流计数、频次统计冒出接近两倍的偏移
- 投放侧反馈说同一访客短时间内在不同目标页之间来回跳
设计要点
决策权用租约来表达,租约到期必须主动放弃,别自动续期——分区期间双方都持有有效租约就完了。接管动作要设冷静期,探测异常后延迟一段时间再执行,把瞬时抖动过滤掉。配置变更在非持有决策权的那一侧进入只读状态,等恢复了再做合并。回切同样需要仲裁,别因为原区恢复了就自动切回去。
适用条件与边界:哪些问题不该由多活容灾解决
适用条件
多活容灾适合满足这些条件的斗篷部署:日均请求量已经达到单可用区承载的较高水位,故障停机的业务代价明显高于多活架构的运维成本;判定链路对时延敏感、冷备切换那种长窗口受不了;团队具备配置版本管理与仲裁机制的实施能力。
不适用的场景
流量规模小、单区故障靠快速重建就能恢复的项目,引入多活只会给配置同步和仲裁增加维护负担。规则变更频率极高、又缺少版本管理流程的团队,多活会把配置分叉的风险放大。再有一种情况,仲裁源本身做不到独立故障域隔离时,多活给你的只是心理安全感,实际可用性没提升。
去年接触过一个做工具类产品投放的团队,斗篷服务部署在两个可用区,日均判定请求量在几十万级别,配置走的是定时同步。某次网络抖动之后,探测把备用区判成了接管方,原区却没收到释放信号,两侧各自对外服务了大约二十分钟。表现出来的问题不是页面打不开,而是同一批访客的跳转目标在两个版本之间来回跳,投放侧的转化数据出现明显断层。排查时先看判定日志,发现两个区都在写,规则版本号差了三个提交。调整分三步走:健康探测从端口存活改成判定接口加版本号校验;引入独立的仲裁服务,决策权改成带租约的形式;配置变更在一侧置为只读,恢复后人工合并。改完又做了一次故障注入演练,故意切断两区之间的同步链路,确认只有一侧继续服务、另一侧进入待接管状态。这套调整没加多少机器,主要成本在流程上。
相邻概念对比:多活容灾、双活与灾备切换的边界
双活强调两个可用区同时承载流量,但它不必然包含决策权仲裁,规则一致时还行,规则一分叉就是脑裂的温床。灾备切换强调的是故障后的恢复能力,允许较长的切换窗口和状态滞后,适合对时延不敏感的链路。多活容灾介于两者之间:平时要承载流量、保持状态新鲜,接管过程又得有仲裁、可收敛。怎么选?看三个维度——故障停机可接受时长、规则变更频率、团队有没有实施仲裁机制的条件。三个维度都指向高要求,那就选多活容灾;只有其中一个指向高要求,双活加人工干预或者灾备切换更划算。
常见概念问题
不等于。它降低的是可用区级故障导致长时间中断的概率,接管过程本身仍有秒级到分钟级的决策窗口;而且仲裁源一旦故障,系统会退化为保守策略,可能暂停部分变更,而不是继续服务。
脑裂防护能否只靠监控告警
不能。告警是事后发现,脑裂期间两侧已经在对外输出不一致的判定结果了。防护必须在决策权授予环节完成,监控只能当兜底验证用。
仲裁服务放在其中一个可用区可以吗
不建议。仲裁源跟被仲裁节点共享故障域的话,那个可用区一挂,仲裁能力跟着一起没了,剩下的可用区拿不到接管授权,多活就退化成单活。