The following document explains common use cases for various read preference modes, as well as counter-indications outlining when you should not change the read preference from the default primary.
读取偏好模式
读取偏好模式 | 说明 |
|---|---|
在大多数情况下,操作将从主节点读取,但如果主节点不可用,则操作将从从节点成员读取。 读取偏好 | |
操作通常从副本集的从节点成员读取数据。如果副本集只有一个主节点成员,并且没有其他成员,则操作将从主节点成员读取数据。 读取偏好 | |
根据指定的延迟阈值,从符合条件的随机副本集成员读取操作,无论该成员是主节点成员还是从节点成员。 该操作在计算延迟时会考虑以下因素:
|
使用非主节点读取偏好的指示
以下是使用非 primary 读取偏好模式的常见用例:
在故障转移期间保持可用性。
如果您希望应用程序在正常情况下从主节点读取数据,但允许在主节点不可用时从从节点读取过时数据,请使用
primaryPreferred。
非主节点偏好的反证
通常请勿使用 secondary 和 secondaryPreferred 为读取提供额外容量,因为:
副本的所有成员都具有大致相等的写入流量;因此,从节点将以与主节点大致相同的速率提供读取服务。
复制是异步的,成功的写入操作与其复制到从节点之间存在一定程度的延迟。从从节点读取可能会返回过时的数据;从不同的从节点读取可能会导致非单调读取。
注意
客户端可以使用客户端会话和因果一致性保证来确保单调读取。
如果副本集中的任何节点变得不可用,则将读取操作分发到从节点可能会影响可用性,因为其余节点必须能够处理所有应用程序请求。
分片通过在一组机器上分配读写操作来增加读写容量,通常是增加容量的更好策略。
请参阅服务器选择算法,进一步了解读取偏好的内部应用。
最大限度提高一致性
为避免过时读取,请使用 primary 读取偏好和 "majority" readConcern。如果主节点不可用,例如在选举期间或当大多数副本集不可访问时,使用 primary 读取偏好的读取操作会产生错误或抛出异常。
在某些情况下,副本集可能暂时有两个主节点;但是,只有一个主节点能够通过 "majority" 写关注确认写入。
部分网络分区可能将主节点 (
Pold) 分隔为包含少数节点的分区,而分区的另一端则包含多数节点。拥有多数节点的分区将选举一个新的主节点 (Pnew),但在短时间内,旧的主节点 (Pold) 可能仍会继续提供读取和写入服务,因为它尚未检测到它只能看到副本集中的少数节点。在此期间,如果旧的主节点 (Pold) 仍然作为主节点对客户端可见,则从该主节点读取的数据可能反映的是过时数据。主节点(
P旧)可能会变得无响应,从而触发选举,可以选举新的主节点(P新)以提供读取和写入服务。如果无响应的主节点(P旧)再次开始响应,则两个主节点将在短时间内可见。当P旧降级时,这个短时间就会结束。但是,在该短时间内,客户端可能会从旧的主节点P旧中读取,可能会提供过时的数据。
要提高一致性,可以禁用自动故障转移;但禁用自动故障转移会牺牲可用性。
可用性最大化
To permit read operations when possible, use primaryPreferred. When there's a primary you will get consistent reads [1], but if there is no primary you can still query secondaries. However, when using this read mode, consider the situation described in secondary vs secondaryPreferred.
| [1] | In some circumstances, two nodes in a replica set may transiently believe that they are the primary, but at most, one of them will be able to complete writes with |
尽量减少延迟
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 会优先选择网络延迟较低的成员,但包含该标记可以让选择更加可预测。
secondary vs secondaryPreferred
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] | 一般来说,避免在副本集中部署仲裁节点,而使用奇数个数据承载节点。如果必须部署仲裁节点,请避免为每个副本集部署多个仲裁节点。 |