【发布时间】:2019-07-11 07:24:59
【问题描述】:
我在一个场景中使用了mongodb,许多线程可能会在DB中插入/更新文档/记录。_id是通过组合所有要插入或更新的_id标识的文档中的字段来构造的。我使用了如下的java代码。我预计在多线程场景中,如果记录/文档不存在,任何线程都可以插入带有_id和线程特定列/字段的新记录/文档,在记录可用后,任何线程都可以更新其线程特定列/字段。但是在测试中,如果记录已经可用,会报错,重复的_id已经可用,但我只将_id放在Filter中而不是在文档中设置。为了解决这个问题,我必须添加一个分布式锁(redis)或捕获 _id 重复异常并在 upsert 设置为 false 的情况下进行更新,但这两者中的任何一个都不是那么整洁,并且都会对超过 100 毫秒的性能产生严重影响。有哪位 mongodb 专家可以帮我解决这个问题?
String rkValue = (String) newObjFromRow;
Bson rkFilter = Filters.eq(rkName, rkValue);
Document document = MyMongoRow.toDocument(row, groupByGuidTsList, groupByGuidTsIndexList);
Document wrappedUpdate = new Document();
wrappedUpdate.put("$set", updateDoc);
updateOneDocWNCompare(rkFilter, MongodbConstants.methodSetOnInsert, document, true);
UpdateOptions options = new UpdateOptions();
options.upsert(true);
collection.updateOne(rkFilter, wrappedUpdate, options);
【问题讨论】:
-
我的首要任务是使用批处理或同步。
-
谢谢你的回复,anton,我也经常使用redis/hbase。对于这些kv风格的数据库,我的问题根本不存在,这些数据库没有插入概念。 batch 不适用于我的情况,因为每个事件都需要立即处理。而 sychronize 是为了在同一个进程中并发,我这里的线程分布在不同的主机上,所以使用分布式锁
-
嗯,某处一定有某种同步。但无论如何,并发 upserts 有什么问题吗?
-
如果文档/记录已经存在,会报错,重复_id已经存在
-
但你认为它会发生还是正在发生?
标签: java multithreading mongodb concurrency upsert