← 返回题目列表

MongoDB 的 Read Preference 是什么?和 Read Concern 有什么区别?

高频 中等 第 5 / 31 题 更新于 2026/07/29
MongoDBRead PreferenceRead Concern复制集

简化版

Read Preference 决定读请求发往复制集的哪个节点,例如默认读 Primary,也可以读 Secondary;Read Concern 决定读到什么一致性级别。一个管“读哪里”,一个管“读到什么保证”,不能混为一谈。

详细版

Read Preference 常见模式有 primaryprimaryPreferredsecondarysecondaryPreferrednearest。默认 primary 能最大程度避免读到旧数据;读 Secondary 可以分担读压力,但可能遇到复制延迟。

Read Concern 则关注可见性和一致性,例如 localmajoritysnapshot。面试回答时可以举例:把 Read Preference 设为 secondary,只是让读走从库,不代表读到最新数据;要结合复制延迟、业务读新鲜度和 Read Concern 一起设计。

完整版教学

一、Read Preference 解决读路由问题

MongoDB 复制集通常有一个 Primary 和多个 Secondary。写请求走 Primary,读请求默认也走 Primary。

Read Preference 用来告诉驱动:读请求应该发给哪个成员。

client read
   |
   v
read preference
   |
   +-- primary
   +-- secondary
   +-- nearest

记忆钩子:Read Preference 问的是“去哪个节点读”,不是“读到多新”。

二、常见模式要知道取舍

模式含义常见用途风险
primary只读主节点默认、强读新鲜度主节点压力更大
primaryPreferred优先主,主不可用读从降级可用性故障时可能读旧
secondary只读从节点报表、低新鲜度读可能复制延迟
secondaryPreferred优先从,从不可用读主读压分摊一致性体验不稳定
nearest按延迟选近节点跨地域读可能读到较旧数据

默认 primary 是保守选择。只有明确能接受旧读,才应该把业务读流量放到 Secondary。

三、Read Concern 是另一件事

Read Concern 决定读取数据的可见性语义。它回答的是:这次读要看到本地已写入的数据,还是多数节点确认的数据,还是事务快照里的数据。

概念回答的问题例子
Read Preference读哪个节点secondaryPreferred
Read Concern读什么一致性级别majority
Write Concern写入确认到什么程度{ w: "majority" }

面试里最容易混的是 Read Preference 和 Read Concern。读从库不等于 majority,一致性级别也不等于读路由。

四、读 Secondary 会遇到复制延迟

假设用户修改昵称,写入 Primary 成功,但 Secondary 还落后 3 秒。

T0 write primary: name = "Alicia"
T1 read secondary: name = "Alice"
T4 secondary catches up: name = "Alicia"

如果业务场景是“用户刚保存资料立刻回显”,这种旧读体验很差。此时应读 Primary,或者对刚写后的读做特殊路由。

如果业务场景是后台报表、推荐计算、异步分析,读 Secondary 可能可以接受。

五、读写分离不是免费午餐

很多人把 Read Preference 当成 MongoDB 读写分离开关,以为读从库就能无脑扩展读能力。

实际要考虑:

  1. Secondary 读压力会影响复制应用速度。
  2. 复制延迟会导致旧读。
  3. 大查询可能拖慢从库,影响故障切换质量。
  4. 跨地域 nearest 可能读到更旧的数据。
  5. 连接串配置错误会让核心链路读到非预期节点。

因此读从库要按业务分层,而不是全局一刀切。

六、工程上怎么设计读策略

可以按读新鲜度分级。

强新鲜度:订单支付结果、用户刚修改资料 -> primary
可短暂旧读:商品详情、内容页 -> primaryPreferred 或 secondaryPreferred
分析查询:报表、离线检查 -> secondary
跨地域低延迟:就近浏览类请求 -> nearest,但要说明旧读风险

在代码中也要避免把全局连接串配置得过于激进。核心写后读链路最好显式使用 Primary。

七、常见误区与追问

  • 误区:Read Preference 和 Read Concern 是一回事。 Read Preference 管读路由,Read Concern 管一致性可见性。
  • 误区:读 Secondary 一定能降低整体压力。 如果从库被大查询压住,复制延迟会扩大,还会影响故障恢复。
  • 误区:nearest 就是最优选择。 它按延迟选节点,可能牺牲读新鲜度。
  • 追问:为什么默认读 Primary? 默认更符合多数业务对写后读新鲜度的预期。
  • 追问:什么场景适合读 Secondary? 报表、分析、低新鲜度列表、可接受延迟的查询。
  • 追问:写后立刻读怎么保证体验? 对该链路读 Primary,或使用会话、因果一致性等机制,并监控复制延迟。

八、加强记忆

Read Preference 记成“读哪里”,Read Concern 记成“读到什么保证”。默认读 Primary 最稳;读 Secondary 能分摊部分读压力,但要承担复制延迟和旧读风险;nearest 更偏低延迟路由,不保证最新。面试回答时用“订单结果读主、报表读从”的例子,最容易把工程取舍讲清楚。