事务性消息
服务通常需要在更新数据的事务中发布消息。数据库的更新和消息的发送都必须在一个事务中进行。否则,服务可能会更新是数据库,然后在消息发送之前崩溃。如果消息不以原子方式执行这两个操作免责类似的故障可能使系统处于不一致的状态。
传统的解决办法是在数据库和消息代理之间使用分布式事务。然而,分布式事务对现今的应用而言不是一个很好的选择。而且,很多新的消息代理,例如Apache Kafka并不支持分布式事务。
因此,应用必须采用不同的机制确保消息的可靠发送。
使用数据库表作为消息队列
我们假设你的应用程序正在使用关系型数据库。可靠地发布消息的直接方法是应用事务性发件箱模式。此模式使用数据库表作为临时消息队列。如下图所示,发送消息的服务有一个OUTBOX数据库表。作为创建、更新和删除业务对象的数据库事务的一部分,服务通过将消息插入到OUTBOX表中来发送消息。这样可以保证原子性,因为这是本地的ACID事务。

OUTBOX表充当临时消息队列。MessageRelay是一个读取OUTBOX表并将消息发布到消息代理的组件。
你可以对某些NoSQL数据库使用类似的方法。作为record存储在数据库中的每个业务实体都有一个属性,该属性是需要发布的消息列表。当服务更新数据库中实体时,他会向该列表附加一条消息。这是原子的,因为它是通过单个数据库操作完成的。但是,挑战在于有效地找到那些拥有事件并发布事件的业务实体。