Java全栈大联盟RabbitMQ系列之可靠性投递消息落库方案

资源干货第一时间送达!

今天安妮就给小伙伴们列举以下几个点:

说明:以下内容非强制或必学,做到了解即可。但是,最好熟练!

1、什么是生产端的可靠性投递

2、可靠性投递解决方案

3、消息落库方案

1、什么是生产端的可靠性投递

可靠性投递需满足四个条件:

1.保障消息的成功发出

2.保障MQ节点的成功接收

3.发送端收到MQ节点(Broker)确认应答

4.完善的消息进行补偿机制

临界值情况:

情况一:生产端投递消息失败,消费端未收到消息。

情况二:生产端投递消息了,消费端也收到了,但在返回应答过程中,突然网络中断了导致发送端未收到确认应答。

对于以上情况,只有保证以上四个条件均满足,才能实现生产端的可靠性投递。

2、可靠性投递解决方案

第一种方案:消息落库,对消息状态进行打标。

在发送消息时,要将消息持久化到数据库中,然后消息设置一个状态,如发送出去,状态为0(发送中),消息到达broker端,broker端返回响应后,将消息状态变更为1(消息已成功收到)。

但是,针对没有收到响应的消息,该怎么做?做一个轮询操作,抓取一些没有OK的消息,设置最大尝试次数,进行重新发送。

第二种方案:消息的延迟投递,做二次确认,回调检查。

3、消息落库方案

以订单为例。

第一步:消息落库。分为两个小步骤,一个是订单业务数据落库,一个是订单message落库。因此,第一件事情把订单业务数据入库(创建订单实体),第二件事情要生产一条消息,将message封装好,然后把这条消息也要入库,设置消息初始状态0,表示消息发送中。

这种方式缺点在于要对数据库数据持久化两次。这里必须保证这两步持久化操作成功,否则立即返回快速失败。

第二步:发送消息给broker

第三步:假设broker收到消息,broker将应答给生产端。

第四步:producer端会有个Confirm Listener异步的监听broker端返回的响应。如果broker端返回true,监听器监听到true后,会将这条指定的消息状态更新为1,表示这条消息已经百分之百的投递成功了。

第五步:分布式定时任务,处理极端情况。假设broker端在回送响应时,网络突然间闪断,这是MSG DB中这条消息永远是初始状态0。

这个时候需要设定一个规则,设置一个临界值timeout,比如5分钟,如果消息5分钟之内还是初始状态0,就需要将这条消息抽取出来,执行第六步重新发送。

或者定时任务设置一个定时间隔,如每隔5分钟抓取一次status为0的订单,这种可能会出现一个小问题,消息刚发出去,定时任务就开始跑了,有一些消息其实是能ACK成功的,但是分布式定时任务又重发了一遍。所以建议是设置一个消息超时的最大时间限制,如5分钟之内这条线消息还没有收到broker端的响应,status还是0,这个时候,再去抽取出来,再执行第六步重新发送。

第六步:重新发送

第七步:设置最大重试次数,超过最大重试次数,将status更新为2表示投递失败。

有一些消息它就是路由不到broker端,比如路由设置的不对,无法成功到达broker端,重试好多次都是失败的。此时需要有个重试次数的限制,如果重试次数为3,大于3次还没有收到响应,则将status设置为2,表示这条消息确认投递失败。

总结:消息投递时,必须考虑极端问题,如消费端一直收不到消息或producer一直收不到broker应答。只有处理好这种极端问题,才能保证消息的可靠性投递。

觉得有用就转发分享一下吧

大家12月份的第三个周三愉快,与你前行

精彩内容

看完本文有收获?请转发分享给更多人

关注「Java全栈大联盟」,提升大神技能

欢迎新旧粉丝(撒花),我是Java全栈大联盟安妮。大家对微信博文有什么问题都可以@我留言,我会尽快回复大家。希望以后可以和各位成为技术道友!

安妮

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181212G0661X00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券