MongoDB WriteConcern与ReadConcern

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MongoDB WriteConcern与ReadConcern相关的知识,希望对你有一定的参考价值。

参考技术A

客户端在写入数据时,可以通过writeConcern来配置写入策略,其包含如下选项

MongoDB Replset复制是通过secondary节点不断拉取primary上的oplog并重放来实现的,那 w:majority 是如何确保写入到大多数的呢?

MongoDB V3.2引入了readConcern来配置读策略,该参数容易与readPreference混淆,两者并不冲突,区别如下:

readConcern设计用于解决脏读问题,例如客户端先在primary读取了一条数据,但该数据还未同步到大多数节点就因为primary down引起的Rollback,那客户端在新primary上无法读取到之前的数据,导致客户端发生了脏读。

readConcern原理

配置 readconcern:majority 需要先确认 replication.enableMajorityReadConcern 参数已经开启。配置该参数后,MongoDB会单独起一个snapshot线程,定期采集数据集的快照,并记录快照对应的oplog时间戳,只有当oplog已经应用到大多数节点时,对应的snapshot才会标记为committed,用户读取就只能读取最后一个committed状态的快照数据。

关闭readconcern

由于readConcern的snapshot保存在内存中,增加了cache的消耗,对性能存在一定影响,如果需要关闭我们可以设置replication.enableMajorityReadConcern为false,并通过在mongod实例上执行db.serverStatus()查看 storageEngine.supportsCommittedReads

关闭也会带来一定的影响,例如:

详细内容可参考 Read Concern "majority"

pymongo 单次插入太慢,尽管 WriteConcern(w=0)

【中文标题】pymongo 单次插入太慢,尽管 WriteConcern(w=0)【英文标题】:pymongo single insert is too slow, despite WriteConcern(w=0) 【发布时间】:2018-04-27 09:11:24 【问题描述】:

我正在使用 pymongo 写入我的 mongodb。 我想要尽可能快的性能,所以我将写关注设置为 w=0。我尝试了三种方法:

1.

client = MongoClient(host=HOST, port=PORT, w=0)
collection = client[DB][COLLECTION]
collection.insert_one(data)

2.

client = MongoClient(host=HOST, port=PORT)
collection = collection.with_options(write_concern=WriteConcern(w=0))
collection = client[DB][COLLECTION]
collection.insert_one(data)

3.

client = MongoClient(host=HOST, port=PORT)
collection = client[DB][COLLECTION]
collection.insert_one(data, bypass_document_validation=True)

在上述所有尝试中,collection.insert_one() 花费的时间约为 0.5 秒 (!)

为什么插入仍然需要这么长时间?

我知道它应该至少是那个时间的五分之一。更何况,“数据”并不是很多数据,只是几个项目。我正在使用 mongodb 3.4 和 pymongo 3.0

【问题讨论】:

【参考方案1】:

首先,您需要回答“多快才够快”。

“慢”和“快”是非常主观的术语。这取决于很多因素,包括配置的服务器、您使用的语言、您插入的文档、您在集合中定义的索引数量,一直到您的期望。

对于某些人来说,“慢”是 >100 毫秒。对于其他人,“慢”是>10ms。当然,您希望获得结果的“速度越快”,您在服务器配置方面的成本就越高。

另一方面,Python 并不是最快的语言。众所周知,在使用Global Interpreter Lock 方面存在限制。它也是一种解释性语言,主要是为了可读性而不是为了速度而设计的。您通常可以使用编译语言(C、C++ 等)立即获得速度提升

您可以尝试的另一件事是使用批量插入,而不是尝试使用insert_one() 插入许多文档。有关使用批量插入的示例,请参阅 http://api.mongodb.com/python/current/examples/bulk.html#bulk-insert。

【讨论】:

谢谢。最让我担心的是 insert_one() 在我添加写入关注点之前和之后所花费的时间非常相似。难道是它没有正确的影响?关于批量插入,这对我来说是个问题,因为我想在每次应用程序运行时向数据库写入少量数据。 @KerenMeron 在这种情况下,从应用程序访问数据库的往返时间远大于副本集节点之间的延迟或写入日志所需的时间。请记住,MongoDB 是一个分布式数据库,这意味着对于时间敏感的应用程序必须考虑网络情况。 WriteConcern 可以让事情变得更快,但它不能比您的网络更快。【参考方案2】:

w=0 将无济于事,除非您正在运行集群。 [1]

co = co.with_options(write_concern=WriteConcern(w=0, j=False, fsync=False)) 为我加快了速度,但请确保您了解后果。可能最好使用insert_many 来加快速度(尤其是如果您的 mongodb 服务器在网络上)。

编辑:实际上可能是侥幸 - 一段时间后放慢了速度。

[1]https://api.mongodb.com/python/current/api/pymongo/write_concern.html#pymongo.write_concern.WriteConcern

【讨论】:

以上是关于MongoDB WriteConcern与ReadConcern的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB 属性Read Preference

mongoDB的事务

MongoDB 学习笔记之 WriteConcern

如何使用 spring mongodb 将 WriteConcern 设置为 ACKNOWLEDGED?

MongoDB 写入策略与读一致性

mongodb官网文档阅读笔记:write concern