Axon MongoDB - message='E11000 重复键错误集合 uniqueAggregateIndex dup key: { : "101", : 0 }
Axon MongoDB - message='E11000 duplicate key error collection uniqueAggregateIndex dup key: { : "101", : 0 }
在我的应用程序中,我们使用 axon 3.3.3 和 mongo 数据库作为事件存储
每当用户更新其个人资料信息时,我们都会保存所有事件。
以下是用例
- 用户已创建个人资料(聚合 ID:101)
在 mongodb(CreateEvent) 中保存了 101 聚合 ID。
用户更新了个人资料,
所以我们想将 UpdateEvent 存储在 mongo db(event store)
但低于异常
13:52:49.643 [http-nio-7030-exec-3] 错误 o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet]在路径 [] 的上下文中抛出异常 [请求处理失败;嵌套异常是 org.axonframework.commandhandling.model.ConcurrencyException:序列 [0] 处的聚合 [101] 的事件已插入] 具有根本原因
com.mongodb.MongoBulkWriteException: 服务器 127.0.0.1:27017 上的批量写入操作错误。写入错误:[BulkWriteError{index=0, code=11000, message='E11000 duplicate key error collection: mytest.domainevents index: uniqueAggregateIndex dup key: { : "101", : 0 }', details={ }}]。
在 com.mongodb.connection.BulkWriteBatchCombiner.getError(BulkWriteBatchCombiner.java:176)
在 com.mongodb.connection.BulkWriteBatchCombiner.throwOnError(BulkWriteBatchCombiner.java:205)
在 com.mongodb.connection.BulkWriteBatchCombiner.getResult(BulkWriteBatchCombiner.java:146)
在 com.mongodb.operation.BulkWriteBatch.getResult(BulkWriteBatch.java:227)
在 com.mongodb.operation.MixedBulkWriteOperation.executeBulkWriteBatch(MixedBulkWriteOperation.java:276)
那么如何保存更新的事件?
下面是 mongo db
中的 uniqueAggregateIndex
{
"aggregateIdentifier" : 1,
"sequenceNumber":1
}
@Value("${mongo.host:127.0.0.1}")
private String mongoHost;
@Value("${mongo.port:27017}")
private int mongoPort;
@Value("${mongo.db:mytest}")
private String mongoDB;
@Bean
public MongoSagaStore sagaStore() {
return new MongoSagaStore(axonMongoTemplate());
}
@Bean
public TokenStore tokenStore(Serializer serializer) {
return new MongoTokenStore(axonMongoTemplate(), serializer);
}
@Bean
public EventStorageEngine eventStorageEngine(Serializer serializer) {
return new MongoEventStorageEngine(serializer, null, axonMongoTemplate(), new DocumentPerEventStorageStrategy());
}
@Bean
public MongoTemplate axonMongoTemplate() {
return new DefaultMongoTemplate(mongo(), mongoDB);
}
@Bean
public MongoClient mongo() {
MongoFactory mongoFactory = new MongoFactory();
mongoFactory.setMongoAddresses(Collections.singletonList(new ServerAddress(mongoHost, mongoPort)));
return mongoFactory.createMongo();
}
Axon 使用该索引来保证聚合上没有并发操作。毕竟Aggregate是一个一致性边界,它上面的所有状态变化都应该是原子的,高度一致的。
将索引更改为 non-unique 是个坏主意。它只允许插入与事件存储中已有的其他事件冲突的事件。
鉴于问题似乎在序列 #0,可能是您不小心将 @CommandHandler
方法建模为构造函数。 Axon 通过创建一个新实例来特殊对待这些命令处理程序,而不是尝试加载现有实例。在您的情况下,聚合已经存在,因为已经存储了一些事件。
在我的应用程序中,我们使用 axon 3.3.3 和 mongo 数据库作为事件存储
每当用户更新其个人资料信息时,我们都会保存所有事件。
以下是用例
- 用户已创建个人资料(聚合 ID:101) 在 mongodb(CreateEvent) 中保存了 101 聚合 ID。
用户更新了个人资料, 所以我们想将 UpdateEvent 存储在 mongo db(event store)
但低于异常
13:52:49.643 [http-nio-7030-exec-3] 错误 o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet]在路径 [] 的上下文中抛出异常 [请求处理失败;嵌套异常是 org.axonframework.commandhandling.model.ConcurrencyException:序列 [0] 处的聚合 [101] 的事件已插入] 具有根本原因 com.mongodb.MongoBulkWriteException: 服务器 127.0.0.1:27017 上的批量写入操作错误。写入错误:[BulkWriteError{index=0, code=11000, message='E11000 duplicate key error collection: mytest.domainevents index: uniqueAggregateIndex dup key: { : "101", : 0 }', details={ }}]。 在 com.mongodb.connection.BulkWriteBatchCombiner.getError(BulkWriteBatchCombiner.java:176) 在 com.mongodb.connection.BulkWriteBatchCombiner.throwOnError(BulkWriteBatchCombiner.java:205) 在 com.mongodb.connection.BulkWriteBatchCombiner.getResult(BulkWriteBatchCombiner.java:146) 在 com.mongodb.operation.BulkWriteBatch.getResult(BulkWriteBatch.java:227) 在 com.mongodb.operation.MixedBulkWriteOperation.executeBulkWriteBatch(MixedBulkWriteOperation.java:276)
那么如何保存更新的事件?
下面是 mongo db
中的 uniqueAggregateIndex{ "aggregateIdentifier" : 1, "sequenceNumber":1 }
@Value("${mongo.host:127.0.0.1}")
private String mongoHost;
@Value("${mongo.port:27017}")
private int mongoPort;
@Value("${mongo.db:mytest}")
private String mongoDB;
@Bean
public MongoSagaStore sagaStore() {
return new MongoSagaStore(axonMongoTemplate());
}
@Bean
public TokenStore tokenStore(Serializer serializer) {
return new MongoTokenStore(axonMongoTemplate(), serializer);
}
@Bean
public EventStorageEngine eventStorageEngine(Serializer serializer) {
return new MongoEventStorageEngine(serializer, null, axonMongoTemplate(), new DocumentPerEventStorageStrategy());
}
@Bean
public MongoTemplate axonMongoTemplate() {
return new DefaultMongoTemplate(mongo(), mongoDB);
}
@Bean
public MongoClient mongo() {
MongoFactory mongoFactory = new MongoFactory();
mongoFactory.setMongoAddresses(Collections.singletonList(new ServerAddress(mongoHost, mongoPort)));
return mongoFactory.createMongo();
}
Axon 使用该索引来保证聚合上没有并发操作。毕竟Aggregate是一个一致性边界,它上面的所有状态变化都应该是原子的,高度一致的。
将索引更改为 non-unique 是个坏主意。它只允许插入与事件存储中已有的其他事件冲突的事件。
鉴于问题似乎在序列 #0,可能是您不小心将 @CommandHandler
方法建模为构造函数。 Axon 通过创建一个新实例来特殊对待这些命令处理程序,而不是尝试加载现有实例。在您的情况下,聚合已经存在,因为已经存储了一些事件。