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

读取偏好使用案例

以下文档解释了各种读取偏好模式的常见使用案例,并通过反证概述了何时不应更改读取偏好的默认值 primary。

读取偏好模式
说明

默认模式。从当前副本集主节点 (primary node in the replica set)读取的操作。

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

操作从主节点 (primary node in the replica set)读取(如果可用)。如果不是,则从符合条件的从从节点(secondary node from replica set)读取。

从副本集符合条件的从从节点(secondary node from replica set)读取的操作。

操作从副本集符合条件的从从节点(secondary node from replica set)读取数据。如果没有符合条件的可用从节点,则操作将从主节点 (primary node in the replica set)节点读取。

操作从网络延迟在延迟窗口内且符合条件的成员中读取,无论它是主节点 (primary node in the replica set)还是从节点(secondary node from replica set)。

重要

读取偏好模式不保证操作成功。可用性和资格决定了客户端会考虑哪些节点,但所选节点仍可拒绝操作,例如当节点处于负载状态时。

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

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

    注意

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

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

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

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

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

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

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

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

    注意

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

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

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

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

为避免过时读取,请使用 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)时,您将获得一致的读取 [1],但如果没有主节点 (primary node in the replica set),您仍然可以查询从节点。但是,在使用此读取模式时,请考虑 secondary 与 secondaryPreferred 中描述的情况。

[1]

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

To always read from a low-latency node, use nearest. The driver or mongos will read from the nearest member and those no more than 15 milliseconds [2] further away than the nearest member.

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

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

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

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

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

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

For specific dedicated queries (e.g. ETL, reporting), you may shift the read load from the primary by using the secondary read preference mode. For this use case, the secondary mode is preferable to the secondaryPreferred mode because secondaryPreferred risks the following situation: if all secondaries are unavailable and your replica set has enough arbiters [3] to prevent the primary from stepping down, then the primary will receive all traffic from the clients. If the primary is unable to handle this load, the queries will compete with the writes. For this reason, use read preference secondary to distribute these specific dedicated queries instead of secondaryPreferred.

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