消息中间件出现消息阻塞如何处理

2020-12-22 11:16发布

消息中间件出现消息阻塞如何处理?

消息中间件出现消息阻塞如何处理?

4条回答
我想吃肉
2楼 · 2020-12-22 13:37

一般生产环境中,如果你有丰富的架构设计经验,都会在使用MQ的时候设计两个队列:一个是核心业务队列,一个是死信队列

核心业务队列,就是比如上面专门用来让订单系统发送订单消息的,然后另外一个死信队列就是用来处理异常情况的。

之所以我们这篇文章抛出一个面试题,结果先长篇大论说一个生产实践案例和业务场景,就是因为面试被问到这个问题时,必须要结合你自己的业务实践经验来说。

你需要先给面试官说有血有肉的业务系统场景,然后再结合这个场景回答他的问题,因为面试官想听的就是你真实的实践经验。

比如说要是第三方物流系统故障了,此时无法请求,那么仓储系统每次消费到一条订单消息,尝试通知发货和配送,都会遇到对方的接口报错。

此时仓储系统就可以把这条消息拒绝访问,或者标志位处理失败!注意,这个步骤很重要。

一旦标志这条消息处理失败了之后,MQ就会把这条消息转入提前设置好的一个死信队列中。

然后你会看到的就是,在第三方物流系统故障期间,所有订单消息全部处理失败,全部会转入死信队列。

然后你的仓储系统得专门有一个后台线程,监控第三方物流系统是否正常,能否请求的,不停的监视。

一旦发现对方恢复正常,这个后台线程就从死信队列消费出来处理失败的订单,重新执行发货和配送的通知逻辑。

死信队列的使用,其实就是MQ在生产实践中非常重要的一环,也就是架构设计必须要考虑的。


纪宇轩
3楼 · 2020-12-22 21:17

mq 中的消息过期失效了

假设你用的是 RabbitMQ,RabbtiMQ 是可以设置过期时间的,也就是 TTL。如果消息在 queue 中积压超过一定的时间就会被 RabbitMQ 给清理掉,这个数据就没了。那这就是第二个坑了。这就不是说数据会大量积压在 mq 里,而是大量的数据会直接搞丢

这个情况下,就不是说要增加 consumer 消费积压的消息,因为实际上没啥积压,而是丢了大量的消息。我们可以采取一个方案,就是批量重导,这个我们之前线上也有类似的场景干过。就是大量积压的时候,我们当时就直接丢弃数据了,然后等过了高峰期以后,比如大家一起喝咖啡熬夜到晚上12点以后,用户都睡觉了。这个时候我们就开始写程序,将丢失的那批数据,写个临时程序,一点一点的查出来,然后重新灌入 mq 里面去,把白天丢的数据给他补回来。也只能是这样了。

假设 1 万个订单积压在 mq 里面,没有处理,其中 1000 个订单都丢了,你只能手动写程序把那 1000 个订单给查出来,手动发到 mq 里去再补一次。



路小雨xiaoyu
4楼 · 2021-03-19 17:15

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



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

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

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

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

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

16ab6f3c6a9a93c1?w=489&h=242&f=png&s=149

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

对于系统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出错而已,不影响别人。




3、经典生产案例:早教盒子APP的发货



接下来用一个经典的生产案例给大家说说MQ在生产的使用。

现在很多早教类的APP,都会提供早教盒子,什么意思呢?

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

1、APP里的早教视频课程

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

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

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

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

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

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

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

1、选择购买早教课程

2、直接支付

3、创建订单

4、给用户增加课程权限

5、通知仓库准备发早教盒子

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

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

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

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

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

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

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

如果对上面过程不太理解的,再看看下面的图,应该就清楚了:

16ab6f3c6b203e81?w=553&h=377&f=png&s=429

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

同时,还得准备好早教盒子的发货(比如说提前打包装箱,准备一些给快递公司使用的发货单之类的,需要帖子箱子上)。

然后通知第三方物流公司的系统,可以去自己的仓库取早教盒子发货了。

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

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

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

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

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

整个过程,如下图所示:

16ab6f3c6aefb146?w=627&h=378&f=png&s=546

这么做有什么好处呢?

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

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

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

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

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




4、死信队列的使用:处理失败的消息



一般生产环境中,如果你有丰富的架构设计经验,都会在使用MQ的时候设计两个队列:一个是核心业务队列,一个是死信队列。

核心业务队列,就是比如上面专门用来让订单系统发送订单消息的,然后另外一个死信队列就是用来处理异常情况的。

之所以我们这篇文章抛出一个面试题,结果先长篇大论说一个生产实践案例和业务场景,就是因为面试被问到这个问题时,必须要结合你自己的业务实践经验来说。

你需要先给面试官说有血有肉的业务系统场景,然后再结合这个场景回答他的问题,因为面试官想听的就是你真实的实践经验。

比如说要是第三方物流系统故障了,此时无法请求,那么仓储系统每次消费到一条订单消息,尝试通知发货和配送,都会遇到对方的接口报错。

此时仓储系统就可以把这条消息拒绝访问,或者标志位处理失败!注意,这个步骤很重要。

一旦标志这条消息处理失败了之后,MQ就会把这条消息转入提前设置好的一个死信队列中。

然后你会看到的就是,在第三方物流系统故障期间,所有订单消息全部处理失败,全部会转入死信队列。

然后你的仓储系统得专门有一个后台线程,监控第三方物流系统是否正常,能否请求的,不停的监视。

一旦发现对方恢复正常,这个后台线程就从死信队列消费出来处理失败的订单,重新执行发货和配送的通知逻辑。

死信队列的使用,其实就是MQ在生产实践中非常重要的一环,也就是架构设计必须要考虑的。

整个过程,如下图所示:

16ab6f3c6b38bdfb?w=712&h=381&f=jpeg&s=25



相关问题推荐

  • 回答 27

    DDL      create table 创建表    alter table  修改表   drop table 删除表   truncate table 删除表中所有行    create index 创建索引   drop index  删除索引 当执行DDL语句时,在每一条语句前后,oracle都将提交当前的事...

  • 回答 23

    java开发应用数据库比较主流的有下面这三种:    1.MySQL   MySQL是最受欢迎的开源SQL数据库管理系统,它由MySQL AB开发、发布和支持。MySQL AB是一家基于MySQL开发人员的商业公司,它是一家使用了一种成功的商业模式来结合开源价值和方法论的第二代开...

  • 回答 23

    1,DML(DataManipulationLanguage):数据操作语言,用来定义数据库记录(数据)2,DCL(DataControlLanguage):数据控制语言,用来定义访问权限和安全级别;3,DQL(DataQueryLanguage):数据查询语言,用来查询记录(数据);4,DDL(DataDefinitionLang...

  • 回答 11

    数据库三级模式:1、外模式,外模式又称子模式或用户模式,对应于用户级,外模式是从模式导出的一个子集,包含模式中允许特定用户使用的那部分数据。用户可以通过外模式描述语言来描述、定义对应于用户的数据记录(外模式),也可以利用数据操纵语言(Data Manip...

  • 回答 11

    模式、外模式、内莫斯,亦称逻辑模式,是数据库中全体数据的逻辑结构和特征的描述,是所有用户的公共数据视图。模式描述的是数据的全局逻辑结构。 外模式涉及的是数据的局部逻辑结构,通常是模式的子集 内模式,亦称存储模式,是数据库在数据系统内部的表示...

  • 回答 16

    为了避免上面出现的几种情况,在标准SQL规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同。未授权读取(Read Uncommitted):允许脏读取,但不允许更新丢失。如果一个事务已经开始写数据,则另外一个数据则不允许同时进行写操作,但允许其他事...

  • 回答 5

    from是个关键词,表示要从哪个表查询。。

  • 回答 12

    数据库池连接数量一直保持一个不少于最小连接数的数量,当数量不够时,数据库会创建一些连接,直到一个最大连接数,之后连接数据库就会等待。

  • 回答 7

    仅用慢日志文件,如何快速获取分时报告?如果有监控系统,获取分时报告(每小时慢查询的条数报告)不难,如果只有慢日志文件,就会有点费劲。实验:通过 pt-query-digest --timeline 功能,可以输出带时间戳的慢查询条目用 sed 将 timeline 报告滤出安装 term...

  • 回答 9
    已采纳

    MySql优化的一般步骤:1.通过show status 命令了解各种sql的执行效率  SHOW STATUS提供msyql服务器的状态信息  一般情况下,我们只需要了解以Com开头的指令  show session status like ‘Com%’:显示当前的连接的统计结果  show global status like ...

  • 回答 4

    有可能是你输入的密码有问题,如果你的密码字母在前数字在后,那么你输入前面的字母后敲回车再输入数字就可以了,可以试一下

  • 回答 5

    工程目录sql语句CREATE TABLE `user` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `username` varchar(32) NOT NULL COMMENT '用户名称',  `birthday` date DEFAULT NULL COMMENT '生日',  `sex` char(1) DEFAUL...

  • 回答 6

    事实上MySQL 能承受的数据量的多少主要和数据表的结构有关,并不是一个固定的数值。表的结构简单,则能承受的数据量相对比结构复杂时大些。据D.V.B 团队以及Cmshelp 团队做CMS 系统评测时的结果来看,MySQL单表大约在2千万条记录(4G)下能够良好运行,经过数...

  • 回答 5

    事实上MySQL 能承受的数据量的多少主要和数据表的结构有关,并不是一个固定的数值。表的结构简单,则能承受的数据量相对比结构复杂时大些。据D.V.B 团队以及Cmshelp 团队做CMS 系统评测时的结果来看,MySQL单表大约在2千万条记录(4G)下能够良好运行,经过数...

  • 回答 6

    mysql哪个版本比较稳定MySQL的选择要取决于用途的,mysql5.5或者5.7 的版本,网上资源较多mysql的版本如下:1. MySQL Community Server 社区版本,开源免费,但不提供官方技术支持。2. MySQL Enterprise Edition 企业版本,需付费,可以试用30天。3. MySQL C...

  • 回答 4

    事实上MySQL 能承受的数据量的多少主要和数据表的结构有关,并不是一个固定的数值。表的结构简单,则能承受的数据量相对比结构复杂时大些。据D.V.B 团队以及Cmshelp 团队做CMS 系统评测时的结果来看,MySQL单表大约在2千万条记录(4G)下能够良好运行,经过数...

没有解决我的问题,去提问