背景
mongo主库现在分片较多,十几个集合表,共计上百亿数据,查询的量比较大,cpu和内存的压力也越来越大,为了更好的利用好mongo,决定使用mongo从库进行常规的查询,减轻主库的负担。
介绍
基本配置说明
mongo读写规则在mongo中的概念为 Read Preference,可以理解为读偏好,或者读配置。
官方文档:https://docs.mongodb.com/manual/core/read-preference/
下图解释 了一些策略模式
读配置模式 | 描述 |
---|---|
primary | 默认模式。从当前主库读取的所有操作 。包含读取操作的多文档事务必须使用primary 的配置策略。给定事务中的所有操作都必须路由到同一个分片。 |
primaryPreferred | 在大多数情况下,操作从主库读取,但如果不可用,则到从库读取。从 version 4.4 开始,primaryPreferred 支持 对分片集群的对冲读取。 |
secondary | 所有操作都到从库读取。从 version 4.4 开始,secondary 支持 对分片集群的对冲读取。如果从库不可用,则抛异常。 |
secondaryPreferred | 在大多数情况下,操作从从库读取,但如果从库不可用,则操作从分片集群上的主库读取。从 version 4.4 开始,secondaryPreferred 支持 对分片集群的对冲读取。 |
nearest | 根据指定的延迟阈值,操作从随机的合格数据库中读取,不一定是主库或者从库。 |
注意事项
- 除了
primary
这个配置读策略,其他的策略都有读到旧数据的风险,因为主从数据库同步时可能有延迟 - 读取偏好不影响数据的可见性,数据内容不会因为配置就会被筛选
详解
primary
所有读取操作仅使用主库。这是默认的读取模式。如果主节点不可用,则读取操作会产生错误或引发异常。
primary
读取配置与使用标签集或maxStalenessSeconds的读取配置项不兼容。如果使用 指定标记集或maxStalenessSeconds
值primary
,启动将产生错误。
包含读取操作的多文档事务必须使用primary
。给定事务中的所有操作都必须路由到同一个分片。
primaryPreferred
在大多数情况下,操作从集合的主库中读取。但是,如果主库不可用,就像在故障转移情况下的情况一样,操作将从 满足读取配置和标记集的从库读取maxStalenessSeconds
。
当primaryPreferred
读取配置包含maxStalenessSeconds 值并且没有可从中读取的主库,客户端通过将辅助节点的最后一次写入与带有最近写入的辅助节点的写入进行比较来估计每个从库数据的陈旧程度。然后,客户端将读取操作定向到估计滞后小于或等于 的辅助节点maxStalenessSeconds
。
当读取首选项包括一个标签集(即一个标签规范列表)并且没有可从中读取的主库时,客户端尝试找到具有匹配标签的次要成员(按顺序尝试标签规范,直到找到匹配项)。如果找到匹配的辅助节点,则客户端从最近的匹配辅助节点组中随机选择一个辅助节点。如果没有辅助节点具有匹配的标签,则读取操作会产生错误。
当读取首选项包含一个maxStalenessSeconds
值 和一个标签集时,客户端首先按陈旧性过滤,然后按指定的标签过滤。
使用该primaryPreferred
模式的读取操作可能会返回陈旧数据。使用该 maxStalenessSeconds
选项可避免从用户估计过于陈旧的辅助数据中读取数据。
secondary
操作仅从集合的从库读取。如果没有可用的辅助节点,则此读取操作会产生错误或异常。
大多数副本集至少有一个辅助节点,但也有可能没有可用的辅助节点的情况。例如,如果成员处于恢复状态或不可用,则具有主节点、辅助节点和 仲裁器的副本集可能没有任何辅助节点。
当secondary
读取首选项包含maxStalenessSeconds 值时,客户端通过将辅助节点的最后一次写入与主节点的写入进行比较来估计每个辅助节点的陈旧程度。然后,客户端将读取操作定向到估计滞后小于或等于 的辅助节点maxStalenessSeconds
。如果没有主服务器,则客户端使用具有最新写入的辅助服务器进行比较。
当读取偏好包括标签集(即标签规范列表)时,客户端尝试找到具有匹配标签的从库(按顺序尝试标签规范直到找到匹配)。如果找到匹配的辅助节点,则客户端从最近的匹配辅助节点组中随机选择一个辅助节点。如果没有辅助节点具有匹配的标签,则读取操作会产生错误。
当读取首选项包含一个maxStalenessSeconds
值 和一个标签集时,客户端首先按陈旧性过滤,然后按指定的标签过滤。
使用该secondary
模式的读取操作可能会返回陈旧数据。使用该 maxStalenessSeconds
选项可避免从客户估计过于陈旧的辅助数据中读取数据。
secondaryPreferred
在大多数情况下,操作从从库读取,但在集合由单个主库(没有数据库)组成的情况下 ,读取操作将使用副本集的主库。
当secondaryPreferred
读取首选项包含maxStalenessSeconds 值时,客户端通过将辅助节点的最后一次写入与主节点的写入进行比较来估计每个辅助节点的陈旧程度。然后,客户端将读取操作定向到估计滞后小于或等于 的辅助节点maxStalenessSeconds
。如果没有主服务器,则客户端使用具有最新写入的辅助服务器进行比较。如果没有估计滞后小于或等于 的辅助节点maxStalenessSeconds
,则客户端将读取操作定向到副本集的主要节点。
当读取偏好包括标签集(即标签规范列表)时,客户端尝试找到具有匹配标签的从库(按顺序尝试标签规范直到找到匹配)。如果找到匹配的辅助节点,则客户端从最近的匹配辅助节点组中随机选择一个辅助节点。如果没有辅助节点具有匹配的标签,客户端将忽略标签并从主节点读取。
当读取首选项包含一个maxStalenessSeconds
值 和一个标签集时,客户端首先按陈旧性过滤,然后按指定的标签过滤。
使用该secondaryPreferred
模式的读取操作可能会返回陈旧数据。使用该 maxStalenessSeconds
选项可避免从客户估计过于陈旧的辅助数据中读取数据。
nearest
驱动程序从网络延迟落在可接受延迟窗口内的成员读取。nearest
模式中的读取在路由读取操作时不考虑数据库是主库还是从库:主库和从库被同等对待。
设置此模式可将网络延迟对读取操作的影响降至最低,而对当前或陈旧数据没有太高的要求。
当读取首选项包含maxStalenessSeconds 值时,客户端通过将辅助节点的最后一次写入与主库的写入进行比较(如果可用)或与具有最近写入的辅助节点(如果没有主库)进行比较来估计每个辅助节点的陈旧程度。然后,客户端将过滤掉估计滞后大于 的任何辅助 maxStalenessSeconds
节点,并将读取随机定向到网络延迟落在可接受延迟窗口内的剩余数据库(主库或者从库) 。
如果您指定一个标签集,客户端会尝试找到一个与指定标签集匹配的副本集数据库,并将读取定向到最近组中的任意数据库。
当读取首选项包含一个maxStalenessSeconds
值 和一个标签集时,客户端首先按陈旧性过滤,然后按指定的标签过滤。从剩余的mongod
实例中,客户端然后随机将读取定向到落入可接受延迟窗口内的实例。阅读首选项成员选择 文档详细描述了该过程。
使用该nearest
模式的读取操作可能会返回陈旧数据。使用该 maxStalenessSeconds
选项可避免从客户估计过于陈旧的辅助数据中读取数据。
总结
最终我们选择了secondaryPreferred的策略配置,优先读取从库,当从库不可用时,故障转移到主库,减少了后续运维的成本。
具体的配置为:
<bean id="secondaryPreferredReadPreference" class="com.mongodb.TaggableReadPreference.SecondaryPreferredReadPreference" />
<bean id="mongoSlaveTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
<property name="readPreference" ref="secondaryPreferredReadPreference" />
</bean>