避免 Spring 数据 MongoDB 中的写入偏差
Avoiding write skews in Spring Data MongoDB
我正在尝试使用 Spring 数据 MongoDB 事务来避免写入偏斜错误。 This diagram explains the flow that happens in my example. I also posted the source code as a whole in this repository.
我读取和更新同一个文档的服务方法是@Transactional
:
fun nextMessage(id: Int, text: String) = transactionReadWrite(id, text)
?.let { messages.save(it) }
@Transactional
fun transactionReadWrite(id: Int, text: String) = threads.findById(id)
?.write(text)
?.let { (threadUpdate, previousLatest) ->
threads.save(threadUpdate)
log.info("Replacing \"${previousLatest.text}\" with \"${threadUpdate.latestMessage.text}\"")
previousLatest
}
但是当我用 5 个不同的输入并行调用 nextMessage()
时,我可以看到其中一些同时读取相同的值,然后成功更新文档:
15:37:06.964 : Opened connection [connectionId{localValue:3, serverValue:1264}] to localhost:27017
15:37:07.308 : Replacing "0" with "3"
15:37:07.308 : Replacing "0" with "4"
15:37:07.310 : Replacing "0" with "1"
15:37:07.430 : Opened connection [connectionId{localValue:5, serverValue:1265}] to localhost:27017
15:37:07.430 : Opened connection [connectionId{localValue:6, serverValue:1266}] to localhost:27017
15:37:07.435 : Replacing "1" with "2"
15:37:07.440 : Replacing "1" with "5"
15:37:07.447 : Replacing "5" with "another one"
如何避免 Spring 数据 MongoDB 事务的写入倾斜错误?
根据图,B3.update应该不会成功,需要在更新中使用optmistic locking,比如updateOne({_id:xx, text:"1"}, $set: { text: "3" })
会return 0 modified
然后 Bobby 需要找到当前实体并再次尝试更新。
我正在尝试使用 Spring 数据 MongoDB 事务来避免写入偏斜错误。 This diagram explains the flow that happens in my example. I also posted the source code as a whole in this repository.
我读取和更新同一个文档的服务方法是@Transactional
:
fun nextMessage(id: Int, text: String) = transactionReadWrite(id, text)
?.let { messages.save(it) }
@Transactional
fun transactionReadWrite(id: Int, text: String) = threads.findById(id)
?.write(text)
?.let { (threadUpdate, previousLatest) ->
threads.save(threadUpdate)
log.info("Replacing \"${previousLatest.text}\" with \"${threadUpdate.latestMessage.text}\"")
previousLatest
}
但是当我用 5 个不同的输入并行调用 nextMessage()
时,我可以看到其中一些同时读取相同的值,然后成功更新文档:
15:37:06.964 : Opened connection [connectionId{localValue:3, serverValue:1264}] to localhost:27017
15:37:07.308 : Replacing "0" with "3"
15:37:07.308 : Replacing "0" with "4"
15:37:07.310 : Replacing "0" with "1"
15:37:07.430 : Opened connection [connectionId{localValue:5, serverValue:1265}] to localhost:27017
15:37:07.430 : Opened connection [connectionId{localValue:6, serverValue:1266}] to localhost:27017
15:37:07.435 : Replacing "1" with "2"
15:37:07.440 : Replacing "1" with "5"
15:37:07.447 : Replacing "5" with "another one"
如何避免 Spring 数据 MongoDB 事务的写入倾斜错误?
根据图,B3.update应该不会成功,需要在更新中使用optmistic locking,比如updateOne({_id:xx, text:"1"}, $set: { text: "3" })
会return 0 modified
然后 Bobby 需要找到当前实体并再次尝试更新。