考虑一个分布式场景中一个常见的场景:服务A执行某个数据库操作成功后,会发送一条消息到消息队列,现在希望只有数据库操作执行成功才发送这条消息。下面是一些常见的作法:
1. 先执行数据库操作,再发送消息
public void purchaseOrder() {
orderDao.save(order);
messageQueue.send(message);
}
复制代码
有可能order新增成功,发送消息失败。最终形成不一致状态。
2. 先发送消息,再执行数据库操作
public void purchaseOrder() {
messageQueue.send(message);
orderDao.save(order);
}
复制代码
有可能消息发送成功,而order新增失败,从而形成不一致状态。
3. 在数据库事务中,先发送消息,再执行数据库操作
@Transactional public void purchaseOrder() {
messageQueue.send(message);
orderDao.save(order);
}
复制代码
这里同样无法保证一致性。如果数据库操作成功,然而消息已经发送了,无法进行回滚。
4. 在数据库事务中,先执行数据库操作,再发送消息
@Transactional public void purchaseOrder() {