先分析在那些情况下可能造成消息的丢失
在日常使用MQ过程,我们来看下图,会发现很多环节会造成数据的丢失。
image.png
针对丢失的情况,如何通过RocketMQ的事务消息来解决
我们还是先来看一张图,根据这图,我们来分析如何根据RocketMQ的事务消息来解决消息丢失问题。
image.png
(1)我们在生产者系统中也就是订单系统中发送一条half消息到MQ中,这个half消息本质是一个订单支付成功的消息,只不过你可以理解为它这个状态是half状态,这个时候积分系统是看不到的,不会接受到该消息。然后我们在订单系统,等待half消息写入成功的响应。
(2)如果在订单系统中我们没有接受到half消息写入成功的响应,此时我们就可以认为此时MQ是有问题的,那么我们就可以在订单系统中处理这笔订单的状态,比如关闭订单,进行退款操作。
(3)如果订单系统接受到了half消息写入成功的消息,那么订单系统就完成自己该完成的业务逻辑,比如更新订单状态等等乱七八糟的东西。
(4)如果订单系统在更新数据库操作,或者处理其他逻辑到时候,本地事务发生异常了,那么我们此时该怎么办呢?别急,没事,RocketMQ已经给我们想号补偿措施了,此时你可以在订单系统中发送一个rollback请求到MQ中,让MQ把之前的half消息给删除掉,这个消息已经有问题了,不能再使用了。
(5)如果订单系统执行自己的业务逻辑以及更新数据库等一系列操作都没有问题,那么此时就需要发送一个commit请求到MQ中了,因为之前的消息是half状态,积分系统是看不见的,MQ必须等到接受到commit请求之后,积分系统才能看到和消费到这条消息。
(6)如果我们再严谨一些,深入吹毛求疵的话,就会发现在图中的第二步,MQ发送了half消息写入成功消息了,但是由于网络原因,订单系统一直没有接受到这个half消息,订单系统则会认为MQ出现问题了,把订单信息更新为关闭状态,然后退款了,那此时MQ会一直保留着这个half状态的消息,此时这half状态的消息该怎么办呢?没事,MQ也做了相应的补偿措施。它会去扫描自己处于half状态的消息,如果这个MQ一直没有接收到对这个half消息执行rollback或commit的命令,操作一定的时间,它就会回调订单系统中的一个接口,它就会问你,这个消息到底现在是什么情况啊,你是要rollback还是commit呢,此时在订单系统中就可以查一下这个订单信息的状态,如果发现已经关闭了并且退款了,那就给MQ发送一个rollback请求。
(7)如果订单系统啥都完成了,并且也发送rollback或commit请求的到MQ,但是由于网络原因,MQ没有接收到该请求这该怎么办,其实道理还是一样的,MQ扫描half消息,如果长时间没有rollback或commit的它会调你的接口,问你是该rollback还是commit。如果发送过去,好巧不巧的,MQ挂了呢,那就等MQ起来,扫描half消息,然后回调接口来问订单系统要咋弄。就这,完事。
网友评论