如何确保 insert() 已传播到副本集的所有成员

How to ensure an insert() has propagated to all members of a replica set

我在插入文档后立即从 MongoDB 集合中检索文档时遇到问题。我正在创建文档,然后 运行 查询(无法提前确定)以获取集合中所有文档的子集。问题是我插入的部分或全部文档未包含在结果中。

过程是:

  1. 查找最近记录的时间戳
  2. 查找自该时间以来发生的交易
  3. 为这些交易生成记录并insert()每一个(这可以而且将会成为一个单一的批量插入)
  4. find()部分记录

文件总是写入成功,但是当我运行 find() 时,经常没有包含新文件。它们会在几秒钟后可用。

我相信当我尝试检索它们时,新文档还没有传播到副本集的所有成员,但我怀疑情况可能并非如此,因为我正在使用相同的连接insert()find().

我相信这可以通过写入问题来解决,但我不确定要指定什么值来确保文档已传播到副本集的所有成员,或者至少是将要使用的成员对于 find() 操作,如果可以提前知道的话。

我不想对成员总数进行硬编码,因为这会在添加另一个成员时中断。 insert() 操作是否慢并不重要。

基本上您正在寻找 write concern,它(用外行的术语来说)允许您指定插入完成的时间。

在 PHP 中,这是通过提供一个 option in the insert statement 来完成的,因此您需要像

这样的东西

w=N Replica Set Acknowledged The write will be acknowledged by the primary server, and replicated to N-1 secondaries.

或者如果您不想硬编码 N:

w= Replica Set Tag Set Acknowledged The write will be acknowledged by members of the entire tag set

$collection->insert($someDoc, ["w" => 3]);

阅读偏好

当您写入集合时,最好将 readPreference 设置为 "primary" 以确保您从与之前相同的 MongoDB 服务器读取写到.

您可以使用 MongoCollection::setReadPreference() 方法。

$db->mycollection->setReadPreference(MongoClient::RP_PRIMARY);
$db->mycollection->insert(['foo' => 'bar']);
$result = $db->mycollection->find([]);

写下关心(不要这样做!)

您可能想使用 write concern 来等待数据通过使用 w=3 复制到所有辅助服务器(对于 3 服务器设置)。然而,这不是要走的路。

MongoDB 复制的好处之一是,它会自动进行故障转移。在那种情况下,您可能只有不到 3 个服务器可以接受数据,导致您的脚本永远等待。

没有w=all写入所有启动的服务器。使用这样的写关注不会很好。刚刚从故障转移中恢复的辅助节点可能会落后数小时,需要很长时间才能赶上。您的脚本会等待(挂起)直到所有辅助节点都被赶上。

一个好的做法是从不在管理任务之外使用w=NN > majority