图解 MongoDB 22|读写关注:持久性与一致性的档位选择

前面几篇多次提到 w: "majority",这篇把它彻底讲清楚。读写关注(read/write concern)是 MongoDB 控制持久性和一致性的核心参数------它们决定了「一个写入要被几个节点确认才算成功」「一个读取从哪个节点读、读到什么程度的一致」。理解了它们,才能在不同业务场景下精准调出「够用且不浪费」的持久性/一致性档位。

先把机制边界说清楚

读写关注是三个相关但独立的参数:

  • writeConcern(写关注):写操作要被几个节点确认才算成功。控制持久性。
  • readPreference(读偏好):读操作发到哪个节点(主还是从)。控制读的分摊和落点。
  • readConcern(读关注):读到什么程度一致的数据。控制读的一致性。

三者可以独立组合。比如「写要 majority + 读从节点分担 + 读到已提交数据」就是一种组合。

writeConcern:写关注档位

writeConcern 的核心是 w 参数,控制写入要几个节点确认。先澄清一个版本事实:5.0 之前复制集默认 writeConcern 是 w: 1,从 5.0 起默认已改为 w: "majority"------今天在 5.0+ 部署上不显式指定,拿到的就是 majority。下面的档位按这个前提理解:

w: 0:不等任何确认,发出就算成功。最快,但可能丢(发出去主就崩了,没记下来)。只适合可丢失的数据:日志、埋点、缓存预热。

w: 1 :等主节点确认(写到了主的内存/journal)。单机不丢(主崩了 journal 能恢复),但复制集下,如果主确认后还没同步到从就崩溃切换,这条写入可能回滚。所以 w: 1 是「单机持久,failover 可能回滚」。在 5.0+ 上它是你主动为了换吞吐而降级到的档位,而不是默认。

w: "majority" :等多数节点确认写入。这是复制集下最强的不丢保证------多数节点都有这条数据,任何少数派故障都不会丢。代价是延迟:要等多数节点同步确认,通常是 w: 1 的两倍以上。这也是 5.0+ 的默认档位。

j: true :强制等 journal 刷盘(而不是只到内存)。配合 w 使用,如 w: 1, j: true 保证单机 journal 已落盘,w: "majority", j: true 是最强档位。journal 刷盘默认每 100ms,j: true 强制立即刷,增加延迟。

档位选择的核心判断是「这条写入能不能容忍丢失」:不能丢(订单、支付)→ w: "majority";单机不丢即可(大多数业务)→ w: 1;可丢(日志)→ w: 0

readPreference:读偏好

readPreference 决定读发到哪个节点:

primary(默认):只读主,强一致(读到主最新写入)。适合一致性敏感的读。

primaryPreferred:优先主,主不可用才读从。兼顾一致性和可用性。

secondary:只读从节点,分担主压力。代价是最终一致(从有延迟,读到旧数据)。

secondaryPreferred:优先读从,从都没有才读主。读密集、对一致性不敏感的场景用。

nearest:读网络延迟最低的节点,不分主从。跨地域部署时用,降低读延迟。

读从节点要配合 maxStalenessSeconds------限制可接受的从节点延迟上限。比如设 90 秒,从节点延迟超过 90 秒就不读它(转读主),避免读到太旧的数据。

readConcern:读关注

readConcern 决定读到什么程度一致的数据:

local(默认):读本节点最新数据。可能读到尚未提交到多数派的数据(主切换时会回滚),所以可能「读到了后来消失的数据」。

majority :只读已提交到多数派的数据。配合 w: "majority" 写,保证读到的数据不会因 failover 回滚消失。核心交易场景建议 majority 读写配对。

linearizable:强一致线性化读,最强但最慢。保证读到所有已确认的写入,且读操作线性一致。代价是延迟高,只在必要时用。

snapshot :快照读,看到某个时间点的一致快照(可用于事务,也可用于单文档读配 atClusterTime 钉住快照)。

怎么组合

实际业务的组合通常是几种模式:

核心交易(订单、支付)w: "majority" 写 + readConcern: "majority" + 读主。最强不丢、最强一致,接受延迟。这是金融级的配置。

一般业务w: 1 写 + 读主。单机不丢、强一致读,延迟低。绝大多数业务够用。注意 5.0+ 默认已是 majority,显式指定 w: 1 是为了把延迟换吞吐,要清楚这是主动降级。

读密集、可容忍最终一致w: 1 写 + readPreference: secondary 读从 + maxStalenessSeconds。分摊主压力,接受从的延迟。

可丢数据(日志、埋点)w: 0 写。换最大吞吐。

跨地域读readPreference: nearest,就近读降低延迟,接受跨地域复制延迟。

判断框架

  • writeConcern 按「能不能丢」选档:不能丢 w:majority,单机不丢 w:1,可丢 w:0
  • 5.0+ 默认 writeConcern 已是 w: "majority",4.x 及以前默认才是 w: 1;排查延迟先确认默认值。
  • j: true 是单机 journal 持久性强保证,绝对不能丢加它。
  • readPreference 按一致性需求选:强一致读主,分摊读从 + maxStalenessSeconds。
  • readConcern 按「读到回滚数据能不能接受」选:不能接受用 majority。
  • 核心交易:majority 写 + majority 读 + 读主,最强档。
  • 读从 = 最终一致,永远记住这点,别用从节点读做强一致判断。

事实边界:读写关注

客观事实先说清:writeConcern 决定写入确认边界,readConcern/readPreference 决定读取一致性与来源。 MongoDB 的优势往往来自"模型、索引、复制/分片和存储引擎"一起配合,而不是某一个配置项单独生效。

工程边界是:把读从库当免费扩展,会引入读旧数据和单调读问题。 所以,MongoDB 文章不能只停留在"机制是什么",还要回答访问模式、数据分布、增长趋势和线上证据是否匹配。

三轮追问

第一轮追问:这个机制真正解决的是什么问题?

writeConcern 决定写入确认边界,readConcern/readPreference 决定读取一致性与来源。

第二轮追问:最容易误用在哪里?

把读从库当免费扩展,会引入读旧数据和单调读问题。

第三轮追问:线上怎么验证这个判断?

按业务选择 majority、linearizable、local 等档位,并压测延迟成本。

下一篇讲两地三中心,把高可用部署架构讲透。


关于十三Tech

All in AI Agent 方向的架构师,专注 AI 工程实践。

相信 AI 是程序员的最佳搭档,帮助每一位开发者驾驭 AI。

公众号搜索「十三Tech」

本文首发:rubyfun.cn/posts/%E5%9...

相关推荐
葫芦和十三8 小时前
图解 MongoDB 21|选举与 failover:Primary 是怎么选出来的
后端·mongodb·agent
GetcharZp8 小时前
26k Star 开源内网穿透神器 NetBird,一分钟实现全球设备互联!
后端
考虑考虑9 小时前
Mybatis实现批量插入
java·后端·mybatis
咖啡八杯10 小时前
GoF设计模式——中介者模式
java·后端·spring·设计模式
带刺的坐椅10 小时前
从 Claude Code 隐私争议,看 SolonCode 的设计选择
ai·llm·agent·claudecode·soloncode·codingplan
lizhongxuan12 小时前
多Agent之间的区别
后端
杨充14 小时前
1.面向对象设计思想
后端
IT_陈寒14 小时前
Java的Date类又坑了我一次,改用时间戳真香
前端·人工智能·后端
后端小肥肠15 小时前
小红书虚拟商品怎么做?我先用 Skill 跑通了壁纸品类
人工智能·aigc·agent