有人知道消息总线实现,它提供对一致性保证的精细控制吗?完全ACID太慢,没有ACID太错误。
我们目前正在使用Rhino ESB包装MSMQ进行消息传递。在分布式事务中使用持久的事务性消息传递时,MSMQ可以在等待I / O完成时阻止提交相当长的时间。
我们的消息分为两大类:业务逻辑和非规范化。后者占消息总线流量的很大比例。
业务逻辑消息需要保证完整的ACID,并且MSMQ已经证明非常适合这一点。
非规范化消息:
(在某些特定情况下,可能会放宽持久性要求,但识别和处理这些情况作为规则的例外会增加复杂性。)
所有非规范化消息都在进程中处理,因此不需要IPC。
如果重新启动该进程,则可以假定所有事务已完成(已提交或已回滚),并且必须恢复尚未处理的所有非规范化消息。重放已经处理的非规范化消息是可以接受的。
据我所知,处理事务的消息传递系统倾向于在完全ACID之间提供选择,或者什么也不提供,ACID会带来性能损失。在某些情况下,我们看到对TransactionScope#Commit()的调用时间长达几百毫秒,具体取决于发送的消息数量。
使用非事务性消息队列会导致在其原始事务完成之前处理消息,从而导致一致性问题。
我们系统的另一部分具有相似的一致性要求但复杂度较低,已经使用了类似于事务日志的自定义实现,并推断出对于这个用例肯定是一种选择,但我宁愿不实现低延迟,如果我不需要,P,并发,持久,事务性消息传递系统:P
在任何人想知道的情况下,要求非规范化消息的持久性的原因在于检测解除和解决desyncs可能分别非常困难和极其昂贵。人们确实注意到某些东西有点错误并且页面刷新无法修复它,因此忽略desyncs不是一种选择。
这不是您正在寻找的答案,但Jonathan Oliver撰写了大量有关如何避免在消息传递中使用分布式事务并保持事务完整性的文章:
http://blog.jonathanoliver.com/2011/04/how-i-avoid-two-phase-commit/ http://blog.jonathanoliver.com/2011/03/removing-2pc-two-phase-commit/ http://blog.jonathanoliver.com/2010/04/idempotency-patterns/
不确定这对你有帮助,但是,嘿。
事实证明,MSMQ + SQL + DTC甚至不提供我们需要的一致性保证。我们以前遇到过一个问题,即在排队的分布式事务已经提交到数据库之前处理消息,导致过时的读取。这是使用ReadCommitted隔离来使用队列的副作用,因为:
我们的要求是B在A的提交中读取表块,这需要Serializable事务,这会带来性能损失。
看起来正常的事情确实是实现必要的约束并保证自己,即使它听起来像重新发明轮子。
有人对此有何评论?
如果你想手动完成这个,这是一个可靠的方法。它满足(1)和(2),它甚至不需要你在(3)和(4)中允许的自由。
当然,这需要非常仔细的实施。
它甚至适用于数据库集群,只要只有一个写节点,并且读取和写入都执行因果关系检查。很可能拥有其中一个就足够了,但是我必须更仔细地考虑这个含义。