如何确保 insert() 已传播到副本集的所有成员
How to ensure an insert() has propagated to all members of a replica set
我在插入文档后立即从 MongoDB 集合中检索文档时遇到问题。我正在创建文档,然后 运行 查询(无法提前确定)以获取集合中所有文档的子集。问题是我插入的部分或全部文档未包含在结果中。
过程是:
- 查找最近记录的时间戳
- 查找自该时间以来发生的交易
- 为这些交易生成记录并
insert()
每一个(这可以而且将会成为一个单一的批量插入)
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=N
和N > majority
。
我在插入文档后立即从 MongoDB 集合中检索文档时遇到问题。我正在创建文档,然后 运行 查询(无法提前确定)以获取集合中所有文档的子集。问题是我插入的部分或全部文档未包含在结果中。
过程是:
- 查找最近记录的时间戳
- 查找自该时间以来发生的交易
- 为这些交易生成记录并
insert()
每一个(这可以而且将会成为一个单一的批量插入) 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=N
和N > majority
。