了解原子操作和竞争条件

时间:2013-09-08 14:53:16

标签: ruby-on-rails mongodb mongoid ruby-on-rails-4 atomicity

假设我有一个包含views_countmales_views_countfemales_views_count字段的集合。我希望能够在查看页面时分别$inc(递增)计数字段。

这个问题是我收到了几个并发连接,并且可能会出现竞争条件。

我一直在阅读Mongodb中的原子操作。他们通常有成功或失败的方法。记录是写入还是不写入。这是否意味着我需要创建逻辑来确定操作是否失败,如果是,请重试它?

回到我的场景。如果我想让每个视图都计数(即使出现竞争条件),该怎么办?我知道Mongodb锁与传统的RDBMS略有不同。通常,我会实现乐观锁定技术。类似于:

begin
  # .. do work .. determine if user is a male or a female
  stat.save
rescue StaleDocumentError
  stat.reload
  retry
end

或者原子操作是否意味着防止竞争条件,因为它是执行更新的服务器,它对真相是什么具有权威性?如果是这样,我们是否还需要实现乐观/悲观锁定技术,或者如果我们使用原子操作,Mongodb会为我们处理这个吗?

1 个答案:

答案 0 :(得分:2)

如果您使用$inc等原子操作,则没有竞争条件。如果您有两个来自不同线程的增量,它们将按照服务器接收的顺序应用,并且在应用这两个操作后,文档的最终结果将是相同的。

如果您使用$set将字段更新为特定值,则“获胜”值将是最后应用的$set。如果您的应用程序用例可能导致相同字段的更新冲突,那么乐观锁定/版本控制将非常有用。

就异常处理而言,您应该假设任何数据库操作都可能导致服务器异常(网络错误,重复键,...)并在适当时重试。原子更新与非原子更新不需要任何特殊逻辑,除非您选择实现自己的乐观锁定(在这种情况下,您可能会重新获取当前版本的文档并重试操作)。

MongoDB手册涵盖了Isolate Sequence of Operations中的几种不同模式。