首页 > 解决方案 > Spring Data MongoDB 并发更新行为

问题描述

想象有一个包含单个字段的文档:{availableSpots: 100}

并且有数百万用户通过向 API 服务器发送请求来争夺一席之地。

每次请求到来时,服务器都会读取文档,如果 availableSpot > 0,则将其减 1,并在另一个集合中创建预订。

现在我读到,每当执行更新操作时,mongodb 都会锁定文档。

如果有一百万个并发请求会发生什么?是否会因为同一个文档一直被锁定而需要很长时间?此外,服务器在尝试更新文档之前读取文档的值,并且在它获取锁时,该位置可能不再可用。

线程也有可能在同一时刻获得“availableSpot > 0”,但实际上availableSpot 可能不足以满足所有请求。如何处理?

标签: mongodbconcurrencymongodb-java

解决方案


这里最重要的是原子性和并发性。

1. 原子性

如果 availableSpots > 0 ,您的更新操作(减一):

db.collection.updateOne({"availableSpots" :{$gt : 0}}, { $inc: { availableSpots: -1 })

是原子的。

$inc 是单个文档中的原子操作。

参考:https ://docs.mongodb.com/manual/reference/operator/update/inc/

2.并发 由于MongoDB对写操作有文档级别的并发控制。每次更新都会锁定文档。

现在你的问题:

如果有一百万个并发请求会发生什么?

是的,每次更新都会一个一个地执行(由于锁定),因此会变慢。

服务器在尝试更新文档之前读取文档的值,并且在它获取锁时,该位置可能不再可用。

由于操作是原子的,因此不会发生这种情况。它将按您的意愿工作,仅执行 100 次更新,受影响的行数大于 0 或等于 1。


推荐阅读