智汇 IT
城启新篇

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

上周三凌晨三点。

手机在枕头边震得快要掉下来。

Kafka积压告警,红色的,标的是1200万条未消费消息。

我摸黑点开手机的时候,企业微信的群消息已经刷了上百条,财务的、运营的、客服的,全在问为什么支付到账延迟了快一小时。

说实话,做了快7年后端,这种场面我见过不下十次,但每次看到那个红色的积压数字,后背还是会冒冷汗。

别上来就盲目加机器

刚工作那会我也傻,一看到积压告警,第一反应就是把consumer实例从3个开到30个。

结果呢?

上次团队里的实习生小周,看到告警直接在控制台点了扩容,开了20个consumer实例,没到5分钟,下游的MySQL连接数直接爆了。

锁表。

整个订单系统直接瘫痪了半小时,比积压本身造成的影响还大。

真的,很多人对积压的第一反应就是扩容,完全不管链路哪里出了问题。你连积压的原因都没摸清楚,加再多机器都是给系统添乱。

Kafka消费积压告警 Grafana面板截图
Kafka消费积压告警 Grafana面板截图

排查得按优先级来,别瞎折腾

我们后来踩了无数坑才总结出来,排查积压根本不需要翻一堆复杂的日志,按顺序捋三个地方就行。

先看生产端的流量曲线。

很多时候根本不是消费端慢了,是生产端突然来了一波流量洪峰。比如上次我们遇到的那次积压,是运营搞了个限时秒杀活动,本来预估峰值QPS是1万,结果实际冲到了8万,生产端10分钟就往队列里塞了平时一天的消息量。

我上次就犯过傻,盯着消费端的日志翻了12分钟,找了半天没发现异常,最后才看到生产端的流量曲线直接飙到了天花板。那12分钟,积压量从800万涨到了1500万,事后被leader拍了一下肩膀,那一下真的疼。

再翻消费端的异常日志。

是不是有什么消息格式不兼容,导致consumer一直报错重试?是不是最近发版改了逻辑,消费一条消息要花原来的3倍时间?这些都是常见的坑。

最后才轮到中间链路的网络排查。

比如机房的交换机是不是出问题了,consumer和Broker之间的网络延迟突然从1ms涨到了100ms,这种情况虽然少见,但遇到了就是大问题。

记住,告警期间每一分钟都值钱,别上来就钻牛角尖翻无关的日志。

消息队列积压排查流程泳道图
消息队列积压排查流程泳道图

扩容不是越多越好

很多人觉得扩容就是把实例数往上拉就行,其实根本不是。

就拿Kafka来说,每个分区同一时间只能被一个consumer实例消费,如果你队列的分区数是32个,那你开33个consumer实例,多出来的那个根本拿不到消息,只会空转占资源。之前我们就干过这种傻事,开了60个consumer,结果只有32个在干活,剩下28个把宿主机的CPU占满了,影响了上面跑的其他服务。

而且扩容也要看瓶颈在哪里。

如果是生产端流量太大,你光加consumer没用,消费的速度赶不上生产的速度,积压只会越来越多。这时候得先给生产端加限流,把非核心的消息先降级,比如什么短信通知、埋点上报的消息,先临时塞到备用队列里,等核心链路的积压清完了再慢慢处理。

如果是下游的数据库有瓶颈,比如写库的TPS最多只能到2000,那你加再多consumer也没用。这时候要先优化下游的写入逻辑,比如原来一条一条写库,改成100条一批批量写,TPS直接就能翻10倍,比你加10个consumer有用多了。

扩容的前提是链路没有单点瓶颈,否则就是给系统添乱。

那次周三的告警,我们最后是这么处理的:

先给生产端加了2倍的限流,把非核心的通知类消息先降级到备用队列。

然后把consumer的批量拉取大小从100调到500,下游写库从单条改成200条一批。

整个链路的消费速度从原来的每秒1200条,直接提到了每秒18000条。

花了15分钟,把1200万的积压全部清完。

说实话,那次之后我们把这套步骤写成了runbook,贴在运维群的公告里。之后再遇到积压,从来没超过半小时处理完。

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