面试中,聊到消息队列,最常见的几个问题就是,如何避免消费到重复数据?如何避免数据丢失?如何顺序消费数据?以及生产故障,消息队列积压数据了怎么办?
今天我们就来讲讲,如果消息队列积压了大量数据,该怎么处理。
一般出现这种情况,是消费者出现问题了,比如消费者有bug,无法正常消费数据,导致消息队列里的数据越积越多。消息队列数据积压还会引起其他的问题,现在许多消息队列,都可以设置数据过期时间,如果积压的数据超过了过期时机,被丢掉了,怎么办?
其实这个问题还挺常见的,笔者之前所在项目里的一个消息队列就遇到过这样的问题,消费者存在bug,它依赖的一个组件出现了问题,导致每次消费数据都不能给broker回复ack,虽然consumer一致在工作,但每次消费数据都失败了,然后消息队列里积压了好几百万的数据。
假设现在我们MQ里积压了几百万到上千万的数据,此时即使消费者恢复了,也需要很久才能消耗掉积压的数据,比如一个消费者一秒消费1000条数据,3 个消费者一秒就是3000条,一分钟就是18万条数据。所以如果你积压了几百万到上千万的数据,即使消费者恢复了,也需要大概1小时的时间才能恢复过来。
这对互联网公司尤其是大点的互联网公司影响是非常大的,稍微大点的互联网公司,一个关键的系统故障了一小时,损失可能就是百万千万级的。
图1 MQ积压了几百万数据
一般这个时候,为了快速把积压的数据处理掉,只能临时紧急扩容了,具体操作步骤和思路如下:
- 先修复 consumer 的问题,确保其恢复消费速度,然后将现有consumer都停掉。
- 新建一个 topic,partition是原来的10倍,临时建立好原先10倍的 queue数量。
- 然后写一个临时的分发数据的consumer程序,这个程序部署上去消费积压的数据,消费之后轮询写入临时建立好的10倍数量的queue中。
- 接着临时征用10倍的机器来部署consumer,每一批consumer消费一个临时queue的数据。这种做法相当于是临时将queue资源和consumer 资源扩大10倍,以正常的10倍速度来消费数据。
- 等快速消费完积压数据之后,再恢复原先部署的架构,重新用原先的 consumer 机器来消费消息。
为了更好说明整个过程,画个图看看:
图2 MQ积压数据解决方案
假如一个消费者每秒消费1000条数据,3个消费者1分钟消费18万条数据,现在有30个消费者,那么每分钟就可以消费180万条数据了。原来需要一个小时消费的数据,现在十分钟就可以处理完。
另外,为了避免磁盘被写满,消息队列可以设置数据过期时间,如果长时间数据积压,就可能导致过期的数据被丢弃。所以通常建议数据过期时间稍微长点,表24小时,48小时。这样如果消息队列出现数据积压,也能即使监测到,在数据过期之前消费掉。
虽然消息队列数据积压的解决方案不是很复杂,但重要的是面对紧急生产故障时的应急能力和反应速度。避免因为技术问题,给公司造成损失。
好了,今天就分享到这里,记得关注我!