我们正在尝试使用updateOne()更新文档。过滤器标识文档,并使用$set更新文档的属性。此更新作业每分钟由cron作业触发。
比如说,原始文档是{_id: "USER1001", status: "INACTIVE"}。我们通过使用过滤器updateOne()调用{_id: "USER1001", status: "INACTIVE"}并将状态字段更新为{"$set":{status:"ACTIVE"}}来更新它。我们查看modifiedCount的结果值,并期望它是1,以声明updateOne()操作是成功的。这就触发了下游的就业。
应用程序在Kubernetes中运行,我们已经对其进行了缩放。当我们在负载下测试系统时,两个同时使用相同过滤器对同一个文档进行updateOne()调用,来自两个不同的荚,并且都将modifiedCount作为1返回。
我们期望modifiedCount对于一个舱是1,对于另一个是0。但对于一些文件,我们看到了这个结果。
样本代码供参考
// cron job that calls update() every minute
func update(){
filter := bson.D{{"_id", "USER1001"}, {"status", "INACTIVE"}}
result, err := collection.UpdateOne(context.Background(), filter, bson.M{"$set": bson.M{"status": "ACTIVE"}})
if result.ModifiedCount != 1 {
// no update done
} else {
// call downstream jobs
}
}我们从应用程序荚中获得的日志行示例
2020-11-20 17:30:58.610518875 +0000 UTC我的工作-7dc8b78bcf-c4677更新():更新结果: USER1001 / Matched=1 / Modified=1
2020-11-20 17:30:58.409843674 +0000 UTC我的工作-7dc8b78bcf-jd7m8更新():更新结果: USER1001 / Matched=1 / Modified=1
问题是-
还有人看到这个behaviour?
。
附加信息,
- POD-2 might run it at,
- 10:00:35
- 10:01:35
- 10:02:35 etc发布于 2020-11-20 19:44:06
如果您首先阅读此文档,发现它是不活动的,然后决定激活它,这是您必须处理的一个常见的竞赛条件。另一个进程执行相同的操作,然后两个进程都更新文档。
有办法防止这种情况发生。Mongodb文档级别的操作是原子的,所以对于您的情况,最简单的解决方案是将过滤器更改为{_id:"USER1001","status":"INACTIVE"},以确保文档在更新时是不活动的。然后只有一个节点将成功地更新文档,尽管多个节点可能试图更新它。
发布于 2020-11-20 23:42:16
我过去也有类似的要求。我建议你尝试使用“锁定”机制。当一个操作运行时,它会防止另一个操作。
如需参考,请查阅:https://www.mongodb.com/blog/post/how-to-select--for-update-inside-mongodb-transactions
官方文件:
需要注意的是,正如我所记得的,Mongo服务器应该是一个“副本集”。不可能是一个。
https://stackoverflow.com/questions/64935868
复制相似问题