使用消息队列要注意异步问题
案情重演: 先从一张时序图开始 首先有两个系统A、B,他们之前用ActiveMQ作为交互。为了记录上面的执行情况,在数据库中有一个字段来标识执行到哪一步的状态,状态说明如下: 1: 插入数据库时的初始状态,即第1步完成后的状态 2: 推送ActiveMQ成功后的状态,也就是第2步完成后的状态 3: 处理结果成功的状态,也就是第6步完成后的状态【最终状态,下面会提到。】
正常来说从步骤1到步骤6都不会有任何问题,但并发量稍微大的时候,最终状态是2而不是3。 而日志打出来的结果已经更新成功,郁闷中,难道是数据库更新的问题? 后来在步骤6的更新数据库前,先查询该条记录判断状态是否为2。 然后下断点,调试,发现此时2的更新数据库操作未完成。 原因分析: 首先,推送MQ成功时并不代表已经处理完毕。 然后,当并发量达到一定程度时,MySQL需要处理大量的update操作,可能造成一定的延迟, 而且是多线程环境,步骤6由专门的线程来执行,跟步骤2实际上是并行的关系。 此时如果处理结果返回时,可能会在步骤2未能执行完毕的情况下执行步骤6成功,然后步骤2 的更新数据库操作会将本就是最终状态的记录变成步骤2完成的状态。
解决方案: 一、在第6步的更新数据库前先判断步骤2的数据库更新操作是否成功。 二、步骤1执行成功后直接推送MQ, 推送成功后不再update, 改为insert新记录到新表中, 查询的时候join一下新表即可。
上一篇:
通过多线程提高代码的执行效率例子
下一篇:
JAVA多线程之——对象锁的理解