智汇 IT
城启新篇

消息队列从来不是系统救急的万能补丁

上周在南京某创业公司的技术沙龙上,有个做电商的小伙子蹲在走廊啃面包,说他们刚被大促的流量打垮,订单接口被回调请求挤到超时,运维连夜拍板上消息队列,结果配完没跑三天,库存对不上了。这事我见多了。

很多人上消息队列的第一动机都是躲锅

说白了,大家对消息队列的最初认知,从来不是什么架构升级的最优解,就是怕接口扛不住。比如原来的同步调用链路,用户点一下下单,要扣库存、减优惠券、发通知、推物流状态,五个接口串在一条线上,任何一个环节卡个两秒,前端转半天圈,用户直接走了。这时候把非核心的环节拆出来丢队列里,前端等核心链路走完直接返回成功,剩下的后台慢慢跑,体验确实立竿见影。

但是麻烦在这——所有你丢进队列里的流程,都默认了”最终一致”,而不是”立刻一致”。那个小伙子遇到的库存错配,就是他把扣库存的逻辑也丢队列里了,用户付完钱,队列堵了十分钟,库存还没扣,后面进来的用户看到还有货,又下了两单,最后超卖了三百多件。

消息队列同步异步调用链路对比示意图
消息队列同步异步调用链路对比示意图

我见过太多团队上队列的时候,只看到了削峰填谷的爽,完全没算过后续要付的代价。比如你以为把请求丢队列就完事了?队列堵了怎么办?消息丢了怎么办?同一个消息被重复消费两次怎么办?这些问题每一个拎出来,都够一个开发熬三个通宵。之前有个做内容社区的团队,为了扛用户发帖的峰值,把所有的UGC内容审核流程全丢进Kafka里,结果某次集群磁盘打满没触发告警,攒了三个小时的消息,等运维发现重启集群的时候,直接把审核服务的CPU干到100%,之前发的帖子全堆在队列里,过了五个小时才全部审完,期间有用户发的违规内容已经被几百个访客看到了,最后赔了不少钱才把舆情压下去。

别把所有的流量都往队列里塞

很多人有个误区,觉得只要是异步的场景,全上队列就对了。错的。比如你做个内部的员工考勤打卡接口,每天的请求量撑死几千次,接口本身写得没毛病,响应时间稳定在20毫秒以内,这时候你非要加个RabbitMQ在中间,图啥?图链路长一点排查问题麻烦?图多维护一套集群增加运维成本?说真的,这种场景加队列,纯纯是给自己找事。

消息队列从来不是架构的必需品,只是用来解决特定场景问题的工具。什么场景真的需要?比如短时间内流量远超过系统能承载的阈值,比如上游服务和下游服务的迭代节奏完全不匹配,比如需要把同一份数据同步给好几个不同的下游系统,这些场景下上队列,才是划算的。

消息队列集群磁盘水位告警监控界面
消息队列集群磁盘水位告警监控界面

我见过不少团队,业务量还没到日活十万的规模,就照着大厂的架构文档抄,把能拆的服务全拆了,能加的中间件全加上,最后光维护这套花架子架构,就要占掉一半的开发精力。有次跟个小团队的技术负责人聊,他说他们当初上消息队列,就是觉得大厂都用,自己不用显得技术不行。结果上了之后,每天的消息量还没到单台服务器容量的5%,每次集群升级都要小心翼翼,生怕出点问题影响业务,算下来投入产出比低到离谱。

你攒的那些技术债,队列都记着

很多团队刚上队列的时候,只觉得开发效率变高了,核心接口的响应时间降了,大促的时候没再崩过,美得不轻。等过个半年一年,系统里的队列从两个变成十个,每个队列里的消息格式没有统一规范,有的生产端发完消息就不管了,消费端挂了重连的时候,才发现之前存的消息已经过期被删了;有的消费逻辑写得有问题,遇到异常就无限重试,把下游接口又打崩了;更麻烦的是出问题的时候,你根本不知道问题出在哪——是生产端没发对?是队列堵了?还是消费端跑飞了?

之前有个老开发跟我吐槽,说他们公司的老系统里有个用了五年的队列,连当初写消费逻辑的人都离职了,每次出问题翻代码,都像在挖别人埋的雷。

这事没那么玄。很多人吹消息队列的三大作用:解耦、削峰、异步。但很少有人告诉你,解耦的代价是链路变长,削峰的代价是消息延迟,异步的代价是一致性风险。你用这个工具拿到的每一个好处,背后都标好了价格。比如你为了削峰,把大促的请求全丢队列里慢慢消费,就得接受用户付完钱之后,可能过个十几秒才能收到支付成功的通知;你为了解耦,把订单系统和库存系统通过队列连起来,就不能指望两个系统的数据永远实时对得上,得自己写对账脚本,每天凌晨跑一遍把差异找出来;你为了异步,把非核心的逻辑从主链路拆出去,就得做好消息丢失的兜底准备,不能默认所有发出去的消息都能被正常消费。

上周跟一个做了十年基础架构的工程师吃饭,他说现在很多团队的技术选型,已经变成了”别人用什么我就用什么”。别人上Kafka我也上Kafka,别人用RocketMQ我也跟着搭一套,根本不管自己的业务场景到底需不需要。最后花了好几周的时间搭起来的集群,实际每天的消息量还没到单台机器承载量的十分之一,光日常的监控、升级、排障,就要占掉开发团队近三分之一的精力。图啥呢?

我从来不是说消息队列不好。它确实是互联网行业发展到今天,被反复验证过的、能扛住超大规模流量的核心组件。但工具永远是工具。你不能因为手里有把锤子,就看什么都是钉子。尤其是做技术的,别总想着靠上一个新组件,就能把所有的问题都解决了。很多时候你系统出问题,根本不是缺个消息队列,是你原来的代码写得太烂,接口设计得太乱,该做的限流、降级、兜底全没做。你把这些基础的事做好了,哪怕不上队列,系统也能稳得一批。

免责声明:市场有风险,选择需谨慎!此文仅供参考,不作买卖依据。如有侵权请联系删除。
文章名称:消息队列从来不是系统救急的万能补丁
文章链接:https://m.itcdj.com/news/785.html