生产环境别再上 MongoDB 仲裁节点了:三起真实事故里的“投票多数”和“写多数”

这篇文章出自 Percona 支持团队的一次内部讨论:把过去接手的真实工单摊开复盘之后,两位作者的结论相当直接——生产环境别再使用仲裁节点(arbiter)。他们并没有说这个功能坏了,而是说它带来的困惑,和今天大家实际跑 MongoDB 的方式已经对不上了。

仲裁节点当年解决的是”投票”,不是”数据”

仲裁节点从 MongoDB 早期版本(2010 年)就存在,设计目标很单纯:帮副本集凑够奇数张选票。团队想要奇数投票成员,又不愿意为此多养一台存数据的节点,于是仲裁节点登场——它很轻量,参与投票,不存数据,也不回放 oplog。

问题在于,这个设计回答的是一个投票问题,它从来没有回答过数据持久化问题,以后也不会。

在 MongoDB 3.x、4.x 时代,持久化从多个方向同时加固:WiredTiger 成为默认存储引擎、副本集协议升级到 pv1、readConcern 和 writeConcern 把”majority”变成一等公民、change streams、多文档事务、流控(flow control)、集群级默认读写关注。这些机制各自都在用某种”多数派”,而仲裁节点只在其中一种里算数。

多数派的种类 谁算数 仲裁节点算不算
选举投票多数 所有投票成员 算
写多数(writeMajority)/ majority 提交点 只有真正存数据的节点 不算
流控与 oplog 应用进度 只有真正存数据的节点 不算

对资深 DBA 来说这几层区分很清楚,对大多数使用者并不清楚。于是就会出现下面这些在支持工单里反复出现的场景。

案例一:选举一切正常,写入却几乎停摆

一个分片集群,三个分片,外加一个配置服务器副本集。每个分片是 7 个投票成员:一个数据中心(DC1)里 3 个数据节点,另一个数据中心(DC2)里 3 个数据节点,第三个数据中心(DC3)里放仲裁节点。配置服务器则是另一种搭法:6 个数据节点,每个机房 2 个,没有仲裁节点。

一个数据中心整体掉线。选举顺利完成,每个分片都选出了新主。几分钟后,每个分片的写入吞吐从大约 每秒 3000-4000 次 掉到 每秒 50-75 次。

应用侧走 mongos,用的是 { w: 2, j: true },每个分片也明明还有 3 个带数据的成员活着——为什么会塌?

一个数据中心掉线后:三个带数据成员加一个仲裁节点仍在线,客户端的 w:2 看起来被满足了
一个数据中心掉线后:三个带数据成员加一个仲裁节点仍在线,客户端的 w:2 看起来被满足了

图:故障后的拓扑,仲裁节点在线但不存数据(图源:Percona 原文)

因为分片集群里有若干内部操作——包括刷新集合路由的那些——走的是带 majority 写关注的本地 no-op,它不看客户端写的 { w: 2 }。在 7 个投票成员、其中 1 个是仲裁节点的拓扑下,writeMajorityCount 等于 4。仲裁节点能投票,但它无法为一次数据写入确认。剩下 3 个可达的数据节点凑不满 4,majority 提交点就此冻结,那些刷新操作卡在一个约 60 秒的硬编码超时上。

配置服务器从头到尾没遇到这个问题:同样掉了一个数据中心之后,它的 6 个数据节点里还有 4 个活着,足够满足它自己的多数派。

3 个机房、6 个数据节点、1 个仲裁节点,纸面上是很强的拓扑。一次故障就把可用性拉了下来,因为真正要等的多数派需要 4 次数据确认,而仲裁节点不在其中。

案例二:流控来了,仲裁节点帮不上忙

另一个副本集:4 个数据节点加 1 个仲裁节点——一个机房 2 个数据节点,另一个机房 2 个数据节点,仲裁节点在第三个站点。

其中一个机房的两个 secondary 在延迟,最坏时落后约 1000 秒;主节点和另一个 secondary 状态正常。这时一个进行中的项目带来大量写入,主节点上的 oplog 生成量暴涨,并级联压到所有 secondary 上。

流控场景:同机房 secondary 正常,另一机房两个 secondary 严重落后,主节点被限速
流控场景:同机房 secondary 正常,另一机房两个 secondary 严重落后,主节点被限速

图:4 个数据节点里只有 2 个追得上,仲裁节点全程在线(图源:Percona 原文)

结果就是流控。4 个数据节点的副本集,提交点只有在至少 3 个数据节点把写入应用之后才会前进。当时追上的只有主节点加 1 个 secondary——2 个不等于 3 个,提交点停住,流控开始在主节点上给写入限速。仲裁节点全程在线,但它不存数据,所以永远不计入这一项。

案例三:P-S-A 上丢掉的一个小时

一个标准的 主-从-仲裁(P-S-A) 副本集。主节点选举优先级为 2,应用用 w: 1 写入。

主节点(N1)宕机,secondary(N2)顶上成为新主——这正是仲裁节点存在的意义。之后大约一个小时里,应用持续写入,而且这些写入都得到了确认。

主节点宕机后,写入只存在于临时主节点 N2 上,仲裁节点没有任何副本
主节点宕机后,写入只存在于临时主节点 N2 上,仲裁节点没有任何副本

图:那一小时的写入只落在临时主 N2 上(图源:Percona 原文)

然后 N1 重新启动,副本集看起来一切正常——但那一个小时的文档不见了。

那些写入当时只存在于临时主节点 N2 上:仲裁节点不存数据,老主节点当时是宕机的,没有任何第三份拷贝。而在追赶阶段,N2 又下去了,N1 还没追平。N1 加上仲裁节点构成多数派,于是 N1 赢得选举、带着它当时的数据成为主节点。当持有那一小时写入的 N2 重新加入时,它领先于共同点,而共同点之后的那段 oplog 属于另一条历史——被回滚,去匹配一个从未见过这些写入的主节点。

回滚路径:N2 重新加入后与 N1 的历史分叉,共同点之后的写入被回滚到 rollback 目录
回滚路径:N2 重新加入后与 N1 的历史分叉,共同点之后的写入被回滚到 rollback 目录

图:分叉与回滚,文档最终从磁盘上找回(图源:Percona 原文)

这些被回滚的文档其实还在磁盘上,以 BSON 形式躺在 dbPath 下的 rollback 目录里,数据就是这样找回来的——但副本集并没有把它们复制出去过。

如果第三个成员是数据节点而不是仲裁节点,故事会不一样:即使应用用 w: 1,一个活着且在复制的第三节点早就有了这些数据,它会领先于 N1、由它接任主节点,N1 从它这里追平之后再按优先级接管。

官方文档其实一直在叠警告

即使这些案例还不够有说服力,手册里同样的提醒已经堆了好几层:

文档建议 内容
优先使用数据节点 三成员副本集里 P-S-S 是推荐方案,P-S-A 只是成本兜底——冗余更弱,数据只有两份完整拷贝
不要同机部署 不要把仲裁节点跑在已经承载主节点或 secondary 的机器上,那台机器一挂,数据和选票一起没了
多个仲裁节点不推荐 从 MongoDB 5.3 起,副本集多仲裁节点支持默认关闭
P-S-A 与 majority secondary 不可用或落后时,majority 写关注会引发性能问题——P-S-A 只要有一个 secondary 出状况就够
分片键与事务 副本集含仲裁节点时不能用事务改分片键;跨多分片的事务只要碰到含仲裁节点的分片就会报错中止
Atlas 任何 MongoDB Atlas 层级都不支持仲裁节点

在已经部署了成千上万个集群的 Atlas 上,用仲裁节点替换数据节点本来是条现成的省钱路径。但权衡下来,这笔节省要付出代价:产品在用户面前失效的风险。

这笔成本账要重新算

仲裁节点过去是、现在也仍然是”用最低成本凑够奇数选票”的办法,但它从来不是获得持久性的办法,而过去十年这个产品一直在把持久性变成集群真正要等的东西。

一旦把风险和坑算进来,”省钱”这件事就开始往另一个方向倾斜:一个卡住的集群要损失多少——写入超时、拉起来的事故群、用户在仪表盘上看着一个 rs.status() 显示正常、对他们却已经不可用的产品。等你算清楚,往往已经晚了,而当初省掉的那个数据节点,才是账单上更便宜的那一行。

如果你已经是资深 MongoDB DBA,这些注意事项对你来说不是新问题,仲裁节点大概也不在你当前的头号麻烦里。对其他人,作者的建议是:生产环境避免使用仲裁节点。它造成的故障看起来不像选举问题,而这类故障恰恰是最难被发现的。

小夏点评

  1. 1. 这篇文章最有价值的地方,是把”多数派”拆成了投票多数和写多数两层。很多团队的拓扑评审只看投票数够不够、奇数还是偶数,而真正决定写入能不能提交的是能确认数据的那几个节点——这两套账在纸面上经常长得不一样。
  2. 2. 三起事故有一个共同结构:平时一切正常,故障发生的几分钟内才暴露仲裁节点”不算数”。P-S-A 拓扑的隐性代价是数据只有两份完整拷贝,而它换来的成本节省,通常抵不过一次事故群里的损失和排查工时。
  3. 3. 对中国 IT 运维和开发者的启示:国内用 MongoDB 的团队里,P-S-A 加仲裁节点是过去十年非常流行的”低成本高可用”方案,尤其在双机房场景。这篇文章值得当作一次拓扑体检清单——把每个副本集的 writeMajority 实际需要的确认数写下来,对照机房故障时还剩几个数据节点,比看监控面板更早发现问题。

参考链接

  • – 原文:Why you should stop using ARBITERS in MongoDB(Percona Blog,2026-10-28,Jean da Silva / Sami Ahlroos)
  • – MongoDB Manual:Replica Set Arbiter、Replica Set Architecture with Three Members
  • – MongoDB Manual:Performance Issues with PSA Replica Sets、Concerns with Multiple Arbiters
  • – MongoDB Manual:Shard Keys, Transactions and Arbiters

您可能还喜欢...

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注