服务一般须要在更新数据的事务中发布消息。数据库的更新和消息的发送都必须在一个事务中进行。不然,服务可能会更新是数据库,而后在消息发送以前崩溃。若是消息不以原子方式执行这两个操做免责相似的故障可能使系统处于不一致的状态。数据库
传统的解决办法是在数据库和消息代理之间使用分布式事务。然而,分布式事务对现今的应用而言不是一个很好的选择。并且,不少新的消息代理,例如Apache Kafka并不支持分布式事务。并发
所以,应用必须采用不一样的机制确保消息的可靠发送。分布式
咱们假设你的应用程序正在使用关系型数据库。可靠地发布消息的直接方法是应用事务性发件箱模式。此模式使用数据库表做为临时消息队列。以下图所示,发送消息的服务有一个OUTBOX数据库表。做为建立、更新和删除业务对象的数据库事务的一部分,服务经过将消息插入到OUTBOX表中来发送消息。这样能够保证原子性,由于这是本地的ACID事务。代理
OUTBOX表充当临时消息队列。MessageRelay是一个读取OUTBOX表并将消息发布到消息代理的组件。cdn
你能够对某些NoSQL数据库使用相似的方法。做为record存储在数据库中的每一个业务实体都有一个属性,该属性是须要发布的消息列表。当服务更新数据库中实体时,他会向该列表附加一条消息。这是原子的,由于它是经过单个数据库操做完成的。可是,挑战在于有效地找到那些拥有事件并发布事件的业务实体。对象