我正在尝试理解mongodb副本集中的读取行为。特别是我的环境具有高读取率,低写入率和相对较小的数据集(比如小于8GB)。我有一个3节点副本集。
我读了这个文件:
http://docs.mongodb.org/manual/core/read-preference/
特别是:
主要默认模式。所有操作都从当前副本集主要读取。
primaryPreferred在大多数情况下,操作从主数据库读取,但如果不可用,则从辅助成员读取操作。
secondary所有操作都从副本集的辅助成员中读取。
secondaryPreferred在大多数情况下,操作从辅助成员读取,但如果没有辅助成员可用,则从主要成员读取操作。
最近的操作从副本集的最近成员读取,无论成员的类型如何。
所以我的理解是默认情况下读取主要内容。有读取首选项允许从辅助(secondary
和secondaryPreferred
)读取。在这些情况下,可能会提供陈旧的数据。
在我看来,最好是在主机和辅助机器上分配读取,以便我可以最好地利用所有3台机器。但我并不认为这是一个选择。以下陈述特别困扰我:
如果读取操作占应用程序流量的很大一部分,则向次要成员分发读取可以提高读取吞吐量。但是,在大多数情况下,分片可以为更大规模的操作提供更好的支持,因为群集可以在一组机器上分配读写操作。
然而,在数据集相对较小的情况下,分片根本没有意义。有人可以对正确的配置有所了解吗?
答案 0 :(得分:0)
我能够使用标记引用https://docs.mongodb.com/manual/tutorial/configure-replica-set-tag-sets/
来部分解决问题conf = rs.conf()
conf.members[1].tags = { "tagType": "dummyValue"}
rs.reconfig(conf)
在每台辅助计算机上设置了自定义标记,并使用标记集(https://docs.mongodb.com/manual/core/read-preference/#tag-sets)
定义了不同的mongo模板(我使用的是Spring Mongo)<bean id="tag" class="com.mongodb.Tag">
<constructor-arg value="tagType" />
<constructor-arg value="dummyValue" />
<bean id="tagSet" class="com.mongodb.TagSet">
<constructor-arg ref="tag" />
</bean>
<bean id="readPref" class="com.mongodb.ReadPreference"
factory-method="secondaryPreferred" >
<constructor-arg ref="tagSet" />
</bean>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoFactory" />
<property name="readPreference" ref="readPref" />
<property name="writeConcern" value="JOURNALED" />
</bean>
使用不同的mongo模板手动分发调用,因此是在辅助mongo服务器上分配负载的部分解决方案。
答案 1 :(得分:0)
我曾在MongoDB的一个论坛上问过这个问题,这是他们的答案,
TL; DR:使用最近的值。
实际上,对群集进行分片肯定会解决问题,因为它将迫使您将数据集拆分为碎片(分片),并且读写操作将由mongos服务器平均分配-前提是您选择了良好的分片键。 但是,正如您所发现的,对于相对较少的数据集,这实际上没有任何意义,而且成本更高。
我们的文档并没有真正揭示出“最近”选项背后的所有魔力,但实际上背后有一个循环算法。 在我们的规范中,您可以阅读更多有关它的信息-特别是可以设置为调整循环算法的选项。
https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.rst#nearest https://github.com/mongodb/specifications/blob/master/source/driver-read-preferences.rst#nearest
To distribute reads across all members evenly regardless of RTT, users should use mode ‘nearest’ without tag_sets or maxStalenessSeconds and set localThresholdMS very high so that all servers fall within the latency window.
这里有更多有关ping times的文档。
特别是这部分:
Once the driver or mongos has found a list of candidate members based on mode and tag sets, determine the “nearest” member as the one with the quickest response to a periodic ping command. (The driver already knows ping times to all members, see “assumptions” above.) Choose a member randomly from those at most 15ms “farther” than the nearest member. The 15ms cutoff is overridable with “secondaryAcceptableLatencyMS”.
此外,您拥有的RAM越多,需要从磁盘检索的文档就越少。如果工作集1较大,则应考虑添加一些RAM以减少IOPS和总体延迟。
除了上面提到的内容外,术语在某些地方并不一致,但是在https://www.mongodb.com/blog/post/server-selection-next-generation-mongodb-drivers中它明确说明了
The ‘localThresholdMS’ variable used to be called secondaryAcceptableLatencyMS, but was renamed for more consistency with mongos (which already had localThreshold as a configuration option) and because it no longer applies only to secondaries.
localThresholdMS
是用作uri选项一部分的连接字符串,文档位于https://mongodb.github.io/mongo-java-driver/4.1/apidocs/mongodb-driver-core/com/mongodb/ConnectionString.html