欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-13 11:14:33
...
先说问题:系统用到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,自己想把
相关标签: MQ SpringBoot