你们是怎么处理 MongoDB 的 WriteConflict 的?

2021-04-07 13:58:23 +08:00
 JasonLaw

javascript - A lot of WriteConflict errors with MongoDB transactions - Stack Overflow中所示,假设一个事务所做的操作是“read-modify-write”,那么在多线程的环境下会出现 WriteConflict 。它介绍了两种解决方案,一种是排队系统,另一种是重新运行系统。个人觉得重新运行系统是不适合在竞争激烈的情况下使用的,那样只能让情况变得更糟。想问一下大家是怎么处理 MongoDB 的 WriteConflict 的?

额外阅读

1864 次点击
所在节点    MongoDB
12 条回复
guyeu
2021-04-07 20:19:08 +08:00
避免 WriteConflict ?
JasonLaw
2021-04-07 21:00:09 +08:00
@guyeu #1 排队系统其实就是避免的一种方法,而重新运行系统更像是“在避免不了或者不避免的情况下,应该怎么做”。但是在竞争激烈的环境下,重新运行系统真的是种好的解决方案吗?
Nillouise
2021-04-08 10:38:56 +08:00
跟 arp 解决冲突思路那样,重新运行系统需要等待一个随机时间,怎么样?
guyeu
2021-04-08 10:52:21 +08:00
@JasonLaw #2 重新运行有一个缺陷,无法预期事务执行的顺序,所以我更倾向于在业务层面进行设计,采用一些手段(包括不仅限于分布式锁)避免数据库层面的写冲突。
JasonLaw
2021-04-08 11:23:37 +08:00
@guyeu #4 “ 重新运行有一个缺陷,无法预期事务执行的顺序”是什么意思?可以举个例子解释一下吗?
guyeu
2021-04-08 13:01:09 +08:00
@JasonLaw #5 你的文章倒数第二段

> MongoDB does lock a document that is being modified by a transaction. However, other sessions that attempt to modify that document do not block. Rather, their transaction is aborted, and they are required to retry the transaction. This is potentially wasteful since other operations in the transaction will need to be re-executed, and also results in requests being serviced in a non-deterministic order.
JasonLaw
2021-04-08 15:29:52 +08:00
@guyeu #6 其实“请求被服务的顺序是不确定的”会更加准确一点。

> results in requests being serviced in a non-deterministic order.
Liuwilliam1
2022-04-08 21:36:43 +08:00
@JasonLaw 老哥,我今天也遇到这个问题,请问怎么具体怎么解决呢,修改那个锁等待时间真的有用吗
JasonLaw
2022-04-08 23:09:50 +08:00
@Liuwilliam1 #8 你的提问是这个吗? https://www.v2ex.com/t/845805

你能提供一下具体能够复现的代码吗?
Liuwilliam1
2022-04-09 09:43:19 +08:00
@JasonLaw
err = c.Mongo.Transaction(ctx, func(sc mongo.SessionContext) error {
err = c.BeforeUpdateStatus(sc, body, model.LogStatusForTotalRank)
if err != nil {
return err
}
opts := options.Update().SetUpsert(true)
query := bson.D{bson.E{Key: "_id", Value: util.CreateKeyString(body.Log.Openid, cast.ToString(body.SubArea))}}
scoreIncValue := util.SumSingleLogScore(body.Log)
update := bson.M{"$inc": bson.M{"score": scoreIncValue}}
_, err = c.Mongo.UpdateOne(sc, util.GetMongoDbRankName(),
util.CreateKeyString(model.MongoDbTableGameTotalRankPre, body.Log.TripartiteId), query, update, opts)
if err != nil {
return err
}
err = c.AfterUpdateStatus(sc, body, model.LogStatusForTotalRank)
if err != nil {
return err
}
return nil
}, nil)

我有四个事务,同时修改某一条记录的不同字段
JasonLaw
2022-04-09 12:21:48 +08:00
@Liuwilliam1 #10 https://www.mongodb.com/community/forums/t/recommended-way-to-handle-write-conflicts-inside-transactions/104491/3

我之前的解决方案是“Just remove the transaction and let the database resolve the writes in the order they come in”。
Liuwilliam1
2022-04-09 15:29:57 +08:00
好的,感谢大佬了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/768701

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX