读偏好默认为primary,事务中必须且只能使用primary;选型需依据数据新鲜度容忍度、可用性要求及是否处于事务中,primary保证强一致,secondary强制读从节点,secondaryPreferred主备自动切换,nearest按延迟选节点但可能读到90秒前数据。

读偏好必须显式配置,不设就是 primary,而且事务里根本不能换——想从从节点读?得先确认场景是否允许过时数据、是否绕开事务限制。
读偏好模式选哪个?看场景不是看名字
别光记“secondary 就是从从节点读”。实际选型得盯住三点:数据新鲜度容忍度、可用性要求、是否在事务里。
-
primary:唯一能用在事务里的模式;写后立刻要读到最新值,必须用它 -
secondary:强制只读从节点,主挂了就报错,适合做离线报表或备份读取 -
secondaryPreferred:主活着就走主,主挂了自动切从,适合读多写少且能接受短暂主从切换的业务 -
nearest:按延迟选节点,但要注意maxStalenessSeconds默认是 90 秒,可能读到 1 分半钟前的数据
标签集怎么配才不踩坑?
标签不是加了就能用,得和副本集成员真实 tags 字段完全匹配,而且顺序决定 fallback 行为。
- 配置成员标签必须用
rs.reconfig(),不能靠连接字符串传 - 标签值只能是字符串,
{"region": "us-east-1"}合法,{"region": 1}会静默失效 - 标签集列表里最后一个元素建议是空文档
{},否则没匹配节点时直接报ReadPreferenceFailed -
primary模式下传标签集会被忽略,驱动会直接报 warning
不同层级怎么覆盖?优先级比想象中更严格
读偏好支持客户端、数据库、集合、游标四级设置,但覆盖规则很硬:低层设了,高层改不了,除非你显式覆盖。
- 连接字符串里加
?readPreference=secondary是客户端级默认,但db.collection.find().readPref("nearest")会覆盖它 - 事务里调
session.startTransaction({ readPreference: "secondary" })会报错,MongoDB 直接拒绝 - Java 驱动里
MongoClientSettings设的ReadPreference.secondary(),到了collection.find()这层还能被.readPreference(ReadPreference.primary())覆盖
最易被忽略的是 maxStalenessSeconds 和 localThresholdMS 的协同影响:前者限制数据最大滞后秒数,后者控制节点延迟容忍范围,两个都设了,驱动会取交集筛选节点——设得太激进,可能筛到最后一个节点都不剩。


















