1

我正在使用 Spring MongoTemplate 与我的 java 应用程序中的 MongoDB 实例集成。我正在运行 mongo 版本 2.4.5 和 spring-data-mongodb 1.2.3-RELEASE。

我在 3 节点副本集中运行 mongoDB,没有分片。

我有数据创建代码,它在同一个线程上依次调用以下两个操作,WriteConcern=ACKNOWLEDGED:

mongoTemplate.insert(entity);
savedEntity = mongoTemplate.findById(entity.getId(), entity.getClass());

我在几个不同的环境中成功运行了这个应用程序,但是在一个环境中,savedEntity偶尔(可能是 100 次执行中的 1 次)被分配了一个空值。数据被插入成功持久化。我已经能够设置一个以 savedEntity == null 为条件的断点,当我点击该断点并强制 findById 通过我的 IDE 再次运行时,它会返回预期的结果(不是 null)。

日志记录表明这些操作在同一个线程(创建 5)上快速连续发生:

2015-01-12 18:32:13,796 DEBUG [create 5] org.springframework.data.mongodb.core.MongoTemplate: Inserting DBObject containing fields: [_class, _id, guid, updated, added, version] in collection: persistentEntity
2015-01-12 18:32:13,798 DEBUG [create 5] org.springframework.data.mongodb.core.MongoTemplate: findOne using query: { "_id" : 4660192} in db.collection: MyDatabase.persistentEntity

在我看来,读取操作是在数据“完全”保存之前发生的,因此找不到匹配的对象。但是不写原子性意味着这不应该发生吗?

我担心我的读取会变成一个陈旧的辅助节点(因为我没有等待我的写入复制)所以我​​重新配置了我的 mongoTemplate 使其配置中只有主节点,但问题并没有消失。

任何答案、对 mongo 写后读行为的澄清或故障排除提示将不胜感激。

4

1 回答 1

0

这个问题的根本原因是我正在运行一个 3 节点副本集,而我的应用程序正在使用readPreference=NEAREST. 这意味着我可以在写入之后但在数据复制到辅助节点之前从辅助节点读取。对于此应用程序,readPreference=PRIMARY 是必需的。

于 2015-09-02T21:07:44.453 回答