微服务开发中经常会使用消息队列进行跨服务通信。在一个典型场景中,服务A执行一个业务逻辑,需要保存数据库,然后通知服务B执行相应的业务逻辑。在这种场景下,我们需要考虑如何发送消息。
1. 基础版
首先,我们可能会考虑将数据库操作和消息发送放在同一个事务中,以下是伪代码示例:
@Transactional public void saveWithMessage(BusinessDO businessDO){ String id = IdUtils.nextId(); businessDO.setId(id); xxxRepository.save(businessDO); BusinessMessage businessMessage = new BusinessMessage(); businessMessage.setKey(id); SendResult send = rocketMQTemplate.syncSend("test-topic", sendMessage); }
在这段代码里通过
@Transactional注解
将数据库的操作以及发送消息放到一个事务中,如果数据库的保存或者消息发送失败,则回滚事务。乍一看似乎没什么问题,但稍微推敲一下就会发现此方式有如下两个缺陷:
1.1 数据不一致
首先最容易想到的是,这种消息发送方式无法保证数据的最终一致性。