关于MQ异步调用,调用失败的处理方式

@Transactional
void a(){
  b();//插入数据a,id=101
  c(101);
}

/*
* 异步执行
*/
@Async
void c(int id){
  // 查询
  Obj data = query(id);
  // 调用mq 
 push(data)
}

在一个事务里面,插入数据,然后在另一个线程里查询并推送数据。

这里query的时候,可能由于事务没有提交,查询不到数据的。

问题

mq异步调用失败,如何保证数据一致性?

已知方案:调用失败写入数据库,然后定时扫表,做补偿,不过感觉这种效率不高。

还有其他更好的方案吗?

回复
阅读 5.2k
2 个回答

按你的使用场景,推送数据必须得在数据创建事务成功之后执行,这里必须有个先后。你可以将推送这个操作异步执行,消息队列有一搬有ack机制,确保消息没丢失。这时候监听消息队列的程序会执行推送,如果推送成功做标记。如果推送失败也标记记录时间,也可以推到另一个消息队列约定多少分钟重试。实在不行就彻底标记失败,或者回滚之前创建的数据。这个才是最终一致性。
如果是并行的操作,就得使用消息队列的confirm机制了。

新手上路,请多包涵

既然c()是插入动作,那么你不妨把这个动作在程序里留一份返回的id当然可以留下来,这时候程序里的就相当于是你查出来的。这样的话query(id)可以完全不用去查询库

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏