并发findandmodify查询成功地更新了同一文档



我有一个用java编写的任务工作者,并使用mongodb 3.4副本集,该副本集运行许多线程本质上是这样做的。

  • 运行任务
  • 通过在MongoDB中更新该任务的文档来表示任务已完成
  • 运行查询以查看此任务中是否完成了所有任务
    • 如果是这样,请继续进行处理的下一阶段
    • 否则,什么都不做

您可以看到,这里有种族条件;多个任务都可以在大约同一时间完成,并认为它们是完成的最后一项任务。我想使用MongoDB来确保仅允许其中一个任务开始处理的下一个阶段。

我有以下代码,该代码旨在确保只有其中一个可以继续(我正在使用Jongo与MongoDB接口(。

Chipset modified = chipsets
  .findAndModify("{_id: #, status: {$ne: #}}", new Object[] { chipset.getId(), Chipset.Status.Queued })
  .with("{$set: {status: #}}", new Object[] { Chipset.Status.Queued })
  .returnNew().as(Chipset.class);
if (modified != null)
    runNextProcessingStep();

在这里很简单;我只是使用FindandModify来更改芯片组(一组任务(的状态。成功进行更改的一个可以执行runnextProcessingstep((。

,或者这就是我认为应该有效的方式。实际上,几个任务,甚至相距2秒的任务,都以某种方式恢复了一个非弹药modified。据我所知,MongoDB在运行FindandModify时应锁定文档,以便可以返回非挂钩文档。

我已经通过FindandModify阅读了可线化的读取,并在其中实现了所有内容。我将连接关注关注与多数派以及可线化的读取有关。我在_id和状态上创建了一个唯一的复合索引。依然没有。也许我误解了发现态度的实际行为?我在做什么错?

好吧,这很尴尬,但是为了成为一个好的互联网公民,我会用发生的事情来更新此消息。还有另一个线程正在从我下面改变状态。我已经说服自己并非如此,但是,有时并发可能是一种真正的痛苦。findandmodify正好工作原理。

最新更新