我有一个WCF服务,其中包括标有OperationBehavior(TransactionScopeRequired=true)
和TransactionFlow(TransactionFlowOption.Allowed)
的操作。
此服务的客户端也是事务的一部分(它也具有数据库。这是一个简化的示例),因此这涉及分布式事务和两阶段提交。
为了使数据库操作支持两阶段提交,我实现了IEnlistmentNotification接口。
在准备阶段,我将数据写入带有事务标记的DB,在提交阶段,从数据中删除事务标记。请注意,提交阶段包括数据库访问,因此可能有点慢。
问题是,从看来和所读内容来看,提交阶段是异步运行的,因此,例如,以下顺序方案可能不起作用:
1)事务1:客户插入A
2)交易2:客户插入依赖于A的B(服务器查找A,从中提取信息,然后使用它来插入B)
由于事务1的提交阶段可能尚未在服务器端完成,因此事务2可能找不到A(因为它仍标记有'transaction 1'标签)。
这2笔交易可能会很快彼此接连发生,因此这取决于比赛条件。
我注意到的方式是,当我启用数据库驱动程序的日志记录时,提交变得有点慢,并且第二个事务发生了错误。如果我禁用了日志记录,那么它将成功。但是,即使我禁用了日志记录,这仍然是竞争状况的问题,在生产环境中我也不会依赖它。
解决此问题的最佳方法是什么?
答案 0 :(得分:1)
我已经遇到了这个问题,我们通过精心策划的传奇来解决了这个问题。您只需实现一个消息队列(apache kafka,rabbit MQ ...)。然后,每个客户端都必须发送一个简单数据作为已执行事件的通知,例如{"event": "projectAdded"...}.
并且您将需要一个协调器,该协调器将订阅该事件并将新事件发送给下一个客户端,例如{"event": "sendNotification"..}
,后者将监听该事件以开始工作。
为了保持一致性,您甚至可以发送一些事件,例如{"error": "projectAdditionFailed"...}
,以便回滚并补偿执行的事件