消息队列积压排查与扩容踩坑实录

上周三凌晨两点四十,手机炸了。运维在群里@所有人,说订单队列的积压量已经飙到1200万条,正常是零。我当时裹着被子爬起来,电脑开机的时候手都在抖——毕竟上次出这种事,还是大促前的压测环境漏了配置。

说实话,我到现在都记得那种深夜被工作砸中的感觉,手机铃声在安静的卧室里响得像火警,第一反应是数据库挂了,等看清群里的积压数值,整个人的困意直接全消了。

别上来就扩容 先搞清楚堵在哪

很多人遇到积压的第一反应,就是去控制台点扩容按钮。我刚工作那会也这样。觉得只要机器够多,什么积压都能消下去。直到那次加了5台机器,积压数反而涨了30%,才反应过来——方向错了,跑的越快错的越远。

先别盯着Broker的监控面板看。拉100条最近队列里的消息样本,看看是不是有固定格式的坏消息在循环。比如上次那次事故,我们翻了20条消息,发现有一半的消息体里的用户ID是空的,消费者拿到之后,要调用用户中心的接口查用户信息,接口因为参数为空,连续返回400,消费者的重试机制就会把消息重新丢回队列,转一圈又被拉出来,再失败,再丢回去。这种场景下,你加100台消费者都没用,反而会因为拉取的坏消息太多,把用户中心的接口打挂,连锁反应能影响半个系统。

遇到积压先采样消息体,别上来就动资源。

Kafka消息队列积压排查链路流程图
Kafka消息队列积压排查链路流程图

我见过太多团队,一看到积压数跳涨,手指就放在扩容按钮上,根本不看根因。最后不仅没把积压消下去,还因为扩容带来的额外压力,把本来正常运行的Broker搞挂,小事变大事。

扩容不是万能药 得算清楚账

当然,也不是说完全不能扩容。但你得先搞清楚,现在的瓶颈到底在哪。是消费者的CPU打满了?是网络带宽被占满了?还是数据库的连接池被耗尽了?

我见过最离谱的扩容操作,是上次隔壁团队遇到积压,直接把消费者的副本数从2调到20,结果发现队列的分区数才8个。多出来的12台消费者,根本拿不到分区的消费权,就那么空转着,每个月多花的云服务器费用,够整个团队吃三次火锅。真的,当时财务看到账单的时候,差点把我们组的云服务器额度给砍了。

消费者实例数永远不能超过队列的分区总数,超过的部分纯纯浪费钱。

还有个坑是,你扩容的时候,别光加消费者的数量,得看看Broker的负载是不是扛得住。之前我们为了消大促的积压,一下加了8台消费者,结果Broker的磁盘IO直接冲到95%,连正常的生产消息都写不进去,本来只是消费慢,结果变成了整个队列集群不可用,前后折腾了三个小时才恢复。别不信。真的会有人犯这种错。

消息队列集群扩容前后资源利用率对比图
消息队列集群扩容前后资源利用率对比图

真遇到积压 最快的止血方法是什么

真遇到积压 最快的止血方法是什么
真遇到积压 最快的止血方法是什么

上次那1200万的积压,我们最后花了1小时40分钟就消完了。没加机器,没换配置。

就是临时把消费者里的非核心逻辑全摘了。原来每条消息的处理流程是:拉消息、解序列化、查订单库、算用户积分、发站内通知、同步用户标签到画像系统。我们当时直接把算积分、发通知、同步标签这三个步骤全注释掉,单条消息的处理耗时从210ms降到12ms,消费速率一下从每秒300条涨到每秒5000条。

等积压量降到安全线以下,我们再开了个独立的离线任务,慢慢把之前没算的积分、没发的通知补跑,用户根本没感知。

说个真事。上次有个刚入职的小伙子,看到积压就慌了,上来就把所有消费者的进程全重启了。本来我们当时已经把积压降到100万了,结果重启的时候,所有的消费位点都要重新提交,消费者重新上线的那10分钟,消息一点没消费,积压直接涨回了300万。当时整个办公室的气氛,真的能冻住。后来我们给组里定了个规矩,遇到积压,谁要是敢随便重启消费者,就得给全组买一周的奶茶。

临时降级非核心消费逻辑,是应对大积压最快的止血手段。比你急着扩容、急着重启有用多了。

哦对,还有个小技巧。要是遇到的积压是因为上游发了大量的坏消息,根本没法正常处理,你别硬扛。直接找个临时的消费者,把这些坏消息全部导到一个死信队列里,先把主队列的积压降下来,再慢慢排查坏消息的来源。别在那死磕,耗的时间越长,业务影响越大。

做了快八年的后端,我现在遇到队列积压,第一反应不是去控制台点扩容。

先泡杯茶。

拉消息样本。

找根因。

再动手。

真的,亏过钱、熬过夜、被运维追着骂过的人,都懂。

免责声明:市场有风险,选择需谨慎!此文仅供参考,不作买卖依据。如有侵权请联系删除。
文章名称:消息队列积压排查与扩容踩坑实录
文章链接:https://www.itcdj.com/it/135.html