`
guazi
  • 浏览: 53609 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

MQ消息太快导致的异步数据查询问题

    博客分类:
  • java
阅读更多
先说问题:系统用到mq发送消息,实际运行时发现mq的接收端程序在接收到消息之后,去查询业务数据的状态时发现仍然是老的状态,导致程序处理数据异常;手动去数据查询时发现是新的状态。
经分析,应该是mqserver和应用在同一个机器,mq消息太快,导致接收端程序查询时,发送端程序的数据库事务还没有提交完成,所以查询到的结果是老的数据。
如果你想思考一下,那就先暂停
-----------------------以下是解决方案------------------------------------------------------
解决方案:最初的方案是接收端延迟执行,拿到消息后 sleep1s,然后再执行,但是这是个很不好的处理,因为1s这个时间对发送端程序来说是不确定的,有可能1s是不够用的,那就用2s,3s?真不是一个好方案,但是勉强能用。
方案改进:后来又再次遇到了同样的问题,于是思考了一番,如下改进步骤:
改进1:既然与事务有关,那能不能把消息发送放在事务提交后?
实现:程序调用mq代理接口发送消息时并不真正的发送消息,而是把消息存储在ThreadLocal中,系统采用的是 springboot的事务管理:DataSourceTransactionManager,实现自定义MyDataSourceTransactionManager 继承 DataSourceTransactionManager,重写 doCommit 方法,在调用完父类的doCommit之后,查看 ThreadLocal中是否有消息,有的话就调用真正的mq发送接口发送消息;重写doCleanupAfterCompletion 方法,调用父类的doCleanupAfterCompletion 后,清理ThreadLocal中的消息。
问题:有的消息发送可能和事务无关,或者发送消息的线程中没有事务,这样就会导致消息没有真正发送
改进2:既然有没有事务的,那是不是可以在程序调用mq代理接口时查询当前线程是否有正在进行的事务,如果有,就存储消息到ThreadLocal,如果没有,就直接发送
实现:可通过 DataSourceTransactionManager.isExistingTransaction来实现
 
问题:在有事务的情况下,事务提交时发送消息,会不会影响到事务的提交?mq发送消息是网络调用,会不会影响程序的效率?
改进3,自己想把
0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics