Appearance
消息的积压处理
1. 大量消息积压
大量消息在 MQ 里积压了几个小时了还没解决。
场景:几千万条数据在 MQ 里积压了七八个小时,从下午 4 点多,积压到了晚上很晚,10 点多,11 点多。线上故障了,这个时候要不然就是修复 consumer 的问题,让他恢复消费速度,然后傻傻的等待几个小时消费完毕。这个肯定不行。一个消费者一秒是 1000 条,一秒 3 个消费者是 3000 条,一分钟是 18 万条,1000 多万条。
所以如果你积压了几百万到上千万的数据,即使消费者恢复了,也需要大概 1 小时的时间才能恢复过来。
1.1. 解决方案
这种时候只能操作临时扩容,以更快的速度去消费数据了。具体操作步骤和思路如下:
- 先修复 consumer 的问题,确保其恢复消费速度,然后将现有 consumer 都停掉;
- 临时建立好原先 10 倍或者 20 倍的 queue 数量(新建一个 topic,partition 是原来的 10 倍);
- 然后写一个临时分发消息的 consumer 程序,这个程序部署上去消费积压的消息,消费之后不做耗时处理,直接均匀轮询写入临时建好分 10 数量的 queue 里面;
- 紧接着征用 10 倍的机器来部署 consumer,每一批 consumer 消费一个临时 queue 的消息;
- 这种做法相当于临时将 queue 资源和 consumer 资源扩大 10 倍,以正常速度的 10 倍来消费消息;
- 等快速消费完了之后,恢复原来的部署架构,重新用原来的 consumer 机器来消费消息;
kafka 的示意图:

2. 大量消息过期
假设你用的是 RabbitMQ,RabbitMQ 是可以设置过期时间的,就是 TTL,如果消息在 queue 中积压超过一定的时间就会被 RabbitMQ 给清理掉,这个数据就没了。那这就是第二个坑了。这就不是说数据会大量积压在 MQ 里,而是大量的数据会直接搞丢。
2.1. 解决方案
这种情况下,实际上没有什么消息积压,而是丢了大量的消息。所以第一种增加 consumer 肯定不适用。
这种情况可以采取 “批量重导” 的方案来进行解决。
在流量低峰期(比如夜深人静时),写一个程序,手动去查询丢失的那部分数据,然后将消息重新发送到 MQ 里面,把丢失的数据重新补回来。
3. 大量消息积压到 MQ 放不下了
如果走的方式是消息积压在 MQ 里,那么如果你很长时间都没处理掉,此时导致 MQ 都快写满了,咋办?这个还有别的办法吗?
3.1. 解决方案
这个就没有办法了,肯定是第一方案执行太慢,这种时候只好采用 “丢弃 + 批量重导” 的方式来解决了。
一、先调整 RabbitMQ 的配置将最大内存上限 vm_memory_high_watermark.relative 调高(默认值是 0.4),二、增加 RabbitMQ 机器的配置。
或者采用 “丢弃 + 批量重导” 的方式来解决了。
首先,临时写个程序,连接到 MQ 里面消费数据将,收到消息之后直接其丢弃,快速消费掉积压的消息,降低 MQ 的压力,然后走第二种方案,在晚上夜深人静时去手动查询重导丢失的这部分数据。