对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。
Docs 菜单

读取偏好使用案例

以下文档解释了各种读取偏好(read preference)模式的常见使用案例,以及概述了何时不应更改默认 读取偏好(readprimary preference)的反证。

读取偏好模式
说明

默认模式。从当前副本集主节点读取的所有操作。

包含读取操作的事务必须使用读取偏好(read preference)primary。给定ACID 事务中的所有操作必须路由到同一成员。

在大多数情况下,操作将从主节点读取,但如果主节点不可用,则操作将从从节点成员读取。

读取偏好 primaryPreferred 支持分片集群上的对冲读

所有操作均会从副本集的辅助成员中读取。

读取偏好 secondary 支持分片集群上的对冲读

操作通常从副本集的从节点成员读取数据。如果副本集只有一个主节点成员,并且没有其他成员,则操作将从主节点成员读取数据。

读取偏好 secondaryPreferred 支持分片集群上的对冲读

根据指定的延迟阈值,从符合条件的随机副本集成员读取操作,无论该成员是主节点成员还是从节点成员。 该操作在计算延迟时会考虑以下因素:

读取偏好 nearest 支持在分片集群上进行对冲读,并且默认启用对冲读选项。

以下是使用非 primary 读取偏好模式的常见用例:

  • 运行不影响前端应用程序的系统操作。

    注意

    读取偏好与单个 mongod 实例的直接连接无关。但是,要在副本集从节点的直接连接上执行读取操作,必须设置读取偏好,例如从节点

  • 为按地理位置分布的应用程序提供本地读取。

    如果应用程序服务器位于多个数据中心,则可以考虑地理分布的副本集或使用非主节点或 nearest 读取偏好。这样客户端可以从延迟最低的节点读取,无需总是从主节点读取。

  • 在故障转移期间保持可用性。

    如果您希望应用程序在正常情况下从主节点读取数据,但允许在主节点不可用时从从节点读取过时数据,请使用 primaryPreferred

通常请勿使用 secondarysecondaryPreferred 为读取提供额外容量,因为:

  • 副本的所有成员都具有大致相等的写入流量;因此,从节点将以与主节点大致相同的速率提供读取服务。

  • 复制是异步的,成功的写入操作与其复制到从节点之间存在一定程度的延迟。从从节点读取可能会返回过时的数据;从不同的从节点读取可能会导致非单调读取。

    注意

    客户端可以使用客户端会话和因果一致性保证来确保单调读取。

  • 如果副本集中的任何节点变得不可用,则将读取操作分发到从节点可能会影响可用性,因为其余节点必须能够处理所有应用程序请求。

分片通过在一组机器上分配读写操作来增加读写容量,通常是增加容量的更好策略。

请参阅服务器选择算法,进一步了解读取偏好的内部应用。

为避免过时读取,请使用 primary 读取偏好和 "majority" readConcern。如果主节点不可用,例如在选举期间或当大多数副本集不可访问时,使用 primary 读取偏好的读取操作会产生错误或抛出异常。

在某些情况下,副本集可能暂时有两个主节点;但是,只有一个主节点能够通过 "majority" 写关注确认写入。

  • 部分网络分区可能将主节点 (P old) 分隔为包含少数节点的分区,而分区的另一端则包含多数节点。拥有多数节点的分区将选举一个新的主节点 (P new),但在短时间内,旧的主节点 (P old) 可能仍会继续提供读取和写入服务,因为它尚未检测到它只能看到副本集中的少数节点。在此期间,如果旧的主节点 (P old) 仍然作为主节点对客户端可见,则从该主节点读取的数据可能反映的是过时数据。

  • 主节点(P )可能会变得无响应,从而触发选举,可以选举新的主节点(P )以提供读取和写入服务。如果无响应的主节点(P )再次开始响应,则两个主节点将在短时间内可见。当 P 降级时,这个短时间就会结束。但是,在该短时间内,客户端可能会从旧的主节点 P 中读取,可能会提供过时的数据。

要提高一致性,可以禁用自动故障转移;但禁用自动故障转移会牺牲可用性。

要尽可能允许读取操作,请使用 。当有主节点primaryPreferred (primary node in the replica set)时,您将获得一致的读取 [],但如果没有主节点 (primary node1 in the replica set),您仍然可以查询从节点。但是,在使用此读取模式时,请考虑secondary 与 中描述的情况。secondaryPreferred

[1]

在某些情况下,副本集的两个节点可能会暂时认为自己是主节点 (primary node in{ w: "majority" } the replica set),但最多其中一个节点能够完成带 写关注(write concern)的写入操作。可以完成{ w: "majority" } 写入的节点是当前主节点 (primary node in the replica set),另一个节点是尚未识别其降级(通常是由于网络分区)的前主节点 (primary node in the replica set)。发生这种情况时,尽管已请求读取偏好(read preference) ,但连接到前主节点 (primary nodeprimary in the replica set)的客户端可能会观察到过时数据,并且对前主节点 (primary node in the replica set)的新写入操作最终将回滚。

要始终从低延迟节点读取数据,请使用 nearest。驱动程序或 mongos 将从最近的节点以及距离最近节点不超过 15 毫秒 [2] 的节点读取。

nearest 保证一致性。如果距离应用程序服务器最近的成员是具有一定复制延迟的从节点,则查询可能返回过时数据。nearest 仅反映网络距离,不反映 I/O 或 CPU 负载。

[2] 此阈值可配置。请参阅 localPingThresholdMs,了解 mongos;或参阅您的驱动程序文档,了解适当的配置。

如果副本集的成员分布在不同地域,您可以基于此创建反映实例位置的副本标签,然后将应用程序配置为查询附近的成员。

例如,如果“东部”和“西部”数据中心的成员标记为 {'dc': 'east'}{'dc': 'west'},则东部数据中心的应用程序服务器可以使用以下读取偏好从附近的成员读取数据:

db.collection.find().readPref('nearest', [ { 'dc': 'east' } ])

虽然 nearest 会优先选择网络延迟较低的成员,但包含该标记可以让选择更加可预测。

对于特定的专用查询(例如ETL、报告),您可以使用 secondary 读取偏好模式将读取负载从主节点转移。对于这个使用案例,secondary 模式比 secondaryPreferred 模式更可取,因为 secondaryPreferred 可能会出现以下情况:如果所有从节点都不可用并且您的副本集有足够的仲裁节点 [3] 以防止主节点让位,那么主节点将接收来自客户端的所有流量。如果主节点无法处理此负载,查询将与写入操作竞争。出于这个原因,请使用读取偏好 secondary 来分配这些特定的专用查询,而不要使用 secondaryPreferred

[3] 一般来说,避免在副本集中部署仲裁节点,而使用奇数个数据承载节点。如果必须部署仲裁节点,请避免为每个副本集部署多个仲裁节点。