专栏名称: 石杉的架构笔记
专注原创、用心雕琢!十余年BAT一线大厂架构经验倾囊相授
目录
相关文章推荐
上饶新闻  ·  敲黑板!《哪吒2》的隐藏知识点来了→ ·  15 小时前  
银幕穿越者  ·  《诡才知道》评分上涨 ... ·  昨天  
桃桃淘电影  ·  9.7分崩到6.4,年度最热新番玩脱了? ·  2 天前  
51好读  ›  专栏  ›  石杉的架构笔记

【真实生产案例】消息中间件如何处理消费失败的消息?

石杉的架构笔记  · 公众号  ·  · 2021-02-26 09:37

正文

长按扫描上方二维码了解

1、消息中间件在生产系统中的使用

下图是一个非常典型的生产环境的问题,很多公司都会在生产系统里使用MQ,即消息队列。


也就是说,一个系统跟另外一个系统之间进行通信的时候,假如系统A希望发送一 消息给系统B,让他去处理。


但是系统A不关注系统B到底怎么处理或者有没有处理好,所以系统A把消息发送给MQ,然后就不管这条消息的“死活”了,接着系统B从MQ里消费出来处理即可。


至于怎么处理,是否处理完毕,什么时候处理,都是系统B的事儿,与系统A无关。


上述过程,可以通过下图看的很清晰:


这样的一种通信方式,就是所谓的“ 异步 ”通信方式


对于系统A来说,只要把消息发给MQ,然后系统B就会异步的去进行处理了,系统A不需要“同步”的等待系统B处理完。


这样的好处是什么呢?


两个字: 解耦


系统A要跟系统B通信,但是他不需要关注系统B如何处理的一些细节。我们来举几个例子说明:


比如,A不需要关注B什么时候处理完,这样假如系统B处理一个消息要耗费10分钟也不关系统A的事儿。


否则,系统A直接调用系统B的接口,系统B一下子处理了10分钟怎么办?难不成系统A也阻塞等待10分钟?


再比如,系统A不需要关注系统B处理成功与否,即使系统B处理失败了,也是系统B自己去考虑这个场景和重新尝试处理。


否则如果系统调用系统B的接口,万一处理失败了报错了,系统A受到一个调用异常该怎么处理?


还有,系统A不需要关注系统B是否存活。万一要是系统B挂掉了,系统A通过MQ来通信也不需要管系统B的“死活”,系统B自己恢复了之后就可以从MQ消费消息再次处理即可。


否则系统A直接调用系统B的接口,万一系统B挂了,难道系统A还要把消息暂存到数据库?等待系统B恢复了再给他发过去吗?


这就是通过MQ进行异步通信,让两个系统解耦之后的好处,可以大幅度提升整个大系统的容错性,增加系统的弹性,而不是处处耦合,一个系统出错连带导致其他系统全部出错。


解耦之后,即使出错也只是大系统中的一个系统B出错而已,不影响别人。



2、生产案例:早教盒子APP的发货

接下来用一个经典的生产案例给大家说说MQ在生产的使用。 现在很多早教类的APP,都会提供早教盒子,什么意思呢?


早教APP提供的核心服务就是三块:


  1. APP里的早教视频课程

  2. 线上微信群的助教答疑指导

  3. 线下送你早教盒子,里面有很多上课道具


这样一个妈妈陪伴孩子上早教的过程可能是这样的:


  • 首先在APP里看早教视频课程,孩子看着很感兴趣。

  • 接着妈妈从早教盒子里取出来道具,陪孩子把视频里的游戏和任务都做一遍,让孩子加深印象

  • 最后每天妈妈会打卡,有助教会来给妈妈进行答疑。


所以说,假设现在我们要在一个早教APP里购买一个早教课程,他的流程大致如下:


  • 选择购买早教课程

  • 直接支付

  • 创建订单

  • 给用户增加课程权限

  • 通知仓库准备发早教盒子

  • 通知物流公司去仓库取早教盒子进行配送。


我们来分析一下每个环节。首先你要是购买一个早教课程,那么点击“购买”的按钮之后,一般直接会跳入一个支付界面。


这个时候,你就可以直接选择支付了。此时后台系统一定会通过支付系统跟第三方支付系统进行通信,比如说支付宝、微信之类的,然后等待支付完成。


一旦支付完成,就会在自己内部系统干两个事:


  • 第一,给这个用户id创建一个订单;

  • 第二,给这个用户id增加看某个早教视频课程的权限。


此时用户其实在“我的订单”界面就可以看到自己的订单了,而且在“我的课程”界面,就可以开始看早教课程的视频了。


下图展示了这个过程:



但是现在问题主要在后面两个步骤,现在你的订单系统作为核心入口,他要通知仓库系统去扣减一个早教盒子的库存。


同时,还得准备好早教盒子的发货(比如说提前打包装箱,准备一些给快递公司使用的发货单之类的,需要帖子箱子上)。 然后通知第三方物流公司的系统,可以去自己的仓库取早教盒子发货了。


这两个步骤需要涉及到对仓库系统以及第三方物流公司系统的调用,那么是采用订单系统直接同步调用那两个系统的方式吗?


恐怕不妥,因为这里最大的问题就是 性能问题 可用性问题


举个例子,假如现在仓库系统部署在其他地方,因为网络问题导致性能很差,访问速度很慢,那么是不是可能会导致用户支付之后,等待了几分钟都看不到整个流程的完成?


或者要是说第三方物流公司的系统现在要是故障了,暂时无法访问,那么会不会导致用户支付了之后,一直没有给用户发货早教盒子?


所以说,在这里就应该引入MQ,订单系统在完成订单的创建以及课程的分配之后,就可以发送一个消息到MQ,然后有一个专门的仓储系统负责消费这个消息,接着尝试去调用独立仓库系统通知发货,以及通知第三方物流系统去配送。


整个过程,如下图所示:



这么做有什么好处呢?


好处是显而易见的,假如现在独立仓库系统和第三方物流系统的访问性能突然变得很差,大不了就是仓储系统在后面慢慢的跟人家通信等着人家处理完毕好了,对订单系统是没影响的。


对于订单系统而言,创建订单和分配课程都是速度很快的,然后发送个消息到MQ速度也很快。


这样一来,用户看到的就是一两秒的时间支付就成功了,然后可以查到订单,看到自己的课程,然后订单的物流显示的是“待配送”的状态。


那么如果独立仓库系统或者第三方物流系统故障了,导致仓储系统消费到一条订单消息之后,尝试进行发货失败,也就是对这条消费到的消息处理失败。这种情况,怎么处理?


这就是本文 最核心 的地方了!!!








请到「今天看啥」查看全文