读偏好用例
以下文档解释了各种读取偏好模式,以及反指示说明何时不应将读取偏好从默认的 primary
更改。
读取偏好模式
读取偏好模式 | 描述 |
---|---|
默认模式。所有操作都从当前副本集的主节点读取。 包含读取操作的分布式事务必须使用读取偏好 | |
在大多数情况下,操作从主节点读取,但如果主节点不可用,则从次节点读取。 | |
所有操作都从副本集的次节点读取。 | |
操作通常从副本集的次节点读取数据。如果副本集只有一个主节点且没有其他成员,则操作从主节点读取数据。 | |
操作从随机合格的副本集成员读取,无论该成员是主节点还是次节点,基于指定的延迟阈值。在计算延迟时,操作考虑以下因素
|
使用非主副本读取偏好的指示
以下是非主读取偏好模式的常见使用场景
运行不影响前端应用程序的系统操作。
注意
读取偏好对于直接连接到单个
mongod
实例不相关。然而,为了在直接连接到副本集的二级成员上执行读取操作,您必须设置读取偏好,例如 secondary。为地理位置分散的应用程序提供本地读取。
如果您在多个数据中心有应用程序服务器,您可以考虑有一个 地理上分散的副本集 并使用非主或
nearest
读取偏好。这允许客户端从最低延迟的成员读取,而不是始终从主节点读取。在故障转移期间保持可用性。
如果您希望应用程序在正常情况下从主节点读取,但在主节点不可用的情况下允许从二级节点进行过时读取,请使用
primaryPreferred
。
非主读取偏好的反指示
一般来说,不要使用 secondary
和 secondaryPreferred
以提供额外的读取能力,因为
副本集中的所有成员写入流量大致相当;因此,次要副本将以与主要副本大致相同的速率服务读取。
复制是异步的,成功写入操作与其在次要副本上的复制之间存在一定延迟。从次要副本读取可能会返回旧数据;从不同的次要副本读取可能会导致非单调读取。
注意
客户端可以使用客户端会话和因果一致性保证来确保单调读取。
如果任何副本成员不可用,则将读取操作分布到次要副本可能会降低可用性,因为剩余的副本成员将需要能够处理所有应用程序请求。
分片通过在多台机器之间分配读取和写入操作来增加读取和写入容量,通常是一种更好的增加容量的策略。
有关读取首选项内部应用的更多信息,请参阅服务器选择算法。
最大化一致性
为了避免旧读取,请使用primary
读取首选项和"majority"
readConcern
。如果主要副本不可用,例如在选举期间或大多数副本集不可访问时,使用primary
读取首选项的读取操作将产生错误或抛出异常。
在某些情况下,副本集可能暂时有两个主要副本;然而,只有具有"majority"
写入关注点的一个主要副本能够确认写入。
部分网络分区可能将一个主要副本(
P
old)隔离到少数节点所在的分区中,而分区的另一侧包含多数节点。多数分区将选举一个新的主要副本(P
new),但在短时间内,旧的主要副本(P
old)可能仍然继续为读取和写入提供服务,因为它尚未检测到它只能看到副本集中的少数节点。在此期间,如果旧的主要副本(P
old)仍作为主要副本可见于客户端,从该主要副本的读取可能会反映旧数据。主节点(
P
旧)可能变得无响应,这会触发选举,并可以选出新的主节点(P
新),用于读取和写入。如果无响应的主节点(P
旧)再次开始响应,将短暂出现两个主节点。当P
旧 退位时,短暂期结束。然而,在短暂期内,客户端可能会从旧的主节点P
旧 读取,这可能会提供过时数据。
为了提高一致性,您可以禁用自动故障转移;然而,禁用自动故障转移会牺牲可用性。
最大化可用性
为了在可能的情况下允许读取操作,使用primaryPreferred
。当有主节点时,您将获得一致的读取[1],但没有主节点时,您仍然可以查询从节点。然而,在使用此读取模式时,请考虑secondary
与 secondaryPreferred
中描述的情况。
[1] | 在某些情况下,复制集中的两个节点可能暂时认为自己是主节点,但最多只有一个节点能够使用{ w: "majority" } 写入关注度完成写入。能够完成{ w: "majority" } 写入的节点是当前主节点,而另一个节点是尚未承认其降级的旧主节点,这通常是由于网络分区。当发生这种情况时,连接到旧主节点的客户端可能会观察到过时数据,尽管他们已经请求了primary 读取偏好,并且旧主节点的新写入最终将回滚。 |
最小化延迟
为了始终从低延迟节点读取,请使用 nearest
。驱动程序或 mongos
将从最近的成员读取,以及那些比最近的成员远15毫秒[2]的成员。
nearest
不保证一致性。如果您应用程序服务器最近的成员是一个次要节点并且有某些复制延迟,查询可能会返回旧数据。nearest
仅反映网络距离,不反映I/O或CPU负载。
[2] | 此阈值可配置。请参阅 localPingThresholdMs 的 mongos 或您驱动程序的文档以获取适当的设置。 |
从地理上分布的成员查询
如果副本集的成员是地理上分布的,您可以根据实例的位置创建副本标签,然后配置应用程序以查询附近的成员。
例如,如果“east”和“west”数据中心中的成员被 标记 为 {'dc': 'east'}
和 {'dc': 'west'}
,则位于东数据中心的您的应用程序服务器可以使用以下读取偏好从附近的成员读取
db.collection.find().readPref('nearest', [ { 'dc': 'east' } ])
尽管 nearest
已优先选择网络延迟低的成员,但包括标签可以使得选择更加可预测。
二级
与 二级首选
相比
对于特定的专用查询(例如 ETL、报告),您可以通过使用 二级
读取偏好模式来将读取负载从主节点转移到二级节点。对于此用例,二级
模式比 二级首选
模式更可取,因为 二级首选
可能会出现以下情况:如果所有二级节点都不可用,并且您的复制集有足够的 仲裁者 [3] 以防止主节点下线,那么主节点将接收所有来自客户端的流量。如果主节点无法处理此负载,则查询将与其他写入操作竞争。因此,使用读取偏好 二级
来分配这些特定的专用查询,而不是使用 二级首选
。
[3] | 通常,避免在复制集中部署仲裁者,而使用奇数个数据节点。如果必须部署仲裁者,请避免在每个复制集中部署超过一个仲裁者。 |