消息队列-如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决?

面试连环炮

面试题

如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有百万消息积压接小时,说说解决思路?

剖析

MQ大幅度积压这件事挺常见的,一般不出,出了的话就是大型生产事故,例如:消费端每次消费之后要写MySQL,结果MySQL挂了,消费端就不动了,或者一直出错,导致消息消费速度极其慢。

场景1:积压大量消息

几千万的消息积压在MQ中七八个小时,这也是一个真实遇到过的一个场景,确实是线上故障了,这个时候要不然就是修复consumer,让他恢复消费速度,然后傻傻的等待几个小时消费完毕,但是很显然这是一种比较不机智的做法。

假设1个消费者1秒消费1000条,1秒3个消费者能消费3000条,一分钟就是18万条,1000万条也需要花费1小时才能够把消息处理掉,这个时候在设备允许的情况下,如何才能够快速处理积压的消息呢?

一般这个时候,只能够做紧急的扩容操作了,具体操作步骤和思路如下所示:

  • 先修复consumer的问题,确保其恢复消费速度,然后将现有consumer都停止
  • 临时建立好原先10倍或者20倍的queue数量
  • 然后写一个临时的分发数据的consumer程序,这个程序部署上去消费积压的数据,消费之后不做耗时的处理,直接均匀轮询写入临时建立好的10倍数量的queue
  • 接着临时征用10倍机器来部署consumer,每一批consumer消费一个临时queue的数据
  • 这种做法相当于临时将queue资源和consumer资源扩大了10倍,以正常的10倍速度

image-20200420160304030

也就是让消费者把消息,重新写入MQ中,然后在用 10倍的消费者来进行消费。

image-20200420160319662

场景2:大量消息积压,并且设置了过期时间

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

这种情况下,就不是说要增加consumer消费积压的消息,因为实际上没有啥积压的,而是丢了大量的消息,我们可以采取的一个方案就是,批量重导,这个之前线上也有遇到类似的场景,就是大量的消息积压的时候,然后就直接丢弃了数据,然后等高峰期过了之后,例如在晚上12点以后,就开始写程序,将丢失的那批数据,写个临时程序,一点点查询出来,然后重新 添加MQ里面,把白天丢的数据,全部补回来。

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

场景3:大量消息积压,导致MQ磁盘满了

如果走的方式是消息积压在MQ里,那么如果你很长时间都没有处理掉,此时导致MQ都快写满了,咋办?

这个时候,也是因为方案一执行的太慢了,只能写一个临时程序,接入数据来消费,然后消费一个丢弃一个,都不要了,快速消费掉所有的消息。然后走第二个方案,到凌晨的时候,在把消息填入MQ中进行消费。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章