政策快报平台从上线到现在,消息队列换了3次。
第1次:用Redis的List做简单队列。
第2次:迁移到RabbitMQ。
第3次:迁移到RocketMQ。
每一次换型,都是因为旧的方案已经无法满足新的需求。每一次换型,也都有代价——数据迁移、代码改造、团队学习成本。
今天复盘这3次选型背后的思考:为什么换、怎么换的、换了之后解决了什么问题。
3次选型
第一次:Redis List(简单队列阶段)
上线初期,消息量很小。每天几千条消息,用Redis的List做队列完全够用。生产者LPUSH,消费者RPOP,简单直接。
优点:无需额外组件,Redis已经在用了,零成本接入。
缺点:不支持消费确认、不支持重试、消息量大时容易积压。
这个阶段持续了大约6个月。直到某天爬虫采集量突然暴增,Redis队列积压了几万条消息,消费者处理不过来,有些消息还没消费就被淘汰了。因为没有确认机制,消息丢失后无法找回。
第二次:RabbitMQ(功能完善阶段)
消息量起来之后,我们开始寻找更专业的消息中间件。RabbitMQ成了当时的选择:
支持消费确认(ACK),消息不会丢失
支持重试和死信队列,失败消息可以重新处理
支持多种路由模式,灵活匹配不同的业务场景
优点:功能全面、稳定、社区活跃。
缺点:使用Erlang编写,运维团队不熟悉,出问题排查困难;吞吐量在单机队列中算不错,但无法水平扩展。
这个阶段持续了大约2年。遇到的最棘手的问题是,高峰期偶尔出现消息积压时,无法快速扩容,只能等流量自然回落。平时还算稳定,但业务增长后碰到了吞吐量瓶颈。
第三次:RocketMQ(大规模分布式阶段)
2025年初,业务进一步增长,消息量已经达到每天数百万条,RabbitMQ开始频繁出现性能瓶颈:消息积压、延迟升高、消费者频繁超时。
经过评估,我们决定迁移到RocketMQ。选择理由是:
支持分布式部署,水平扩展能力强
吞吐量高(单机支持十万级QPS)
支持事务消息、延时消息
支持消息轨迹追踪,问题排查方便
阿里出品,Java技术栈,团队熟悉,运维成本低
迁移过程大致分了三个阶段,持续了约1个月。先双跑验证,再灰度切流,最后全量切换,控制风险。
选型决策的一些思考
| 选型 | 适用场景 | 不适用场景 |
|---|---|---|
| Redis List | 消息量小(万级/天)、允许少量丢失 | 消息量大、需要确认机制 |
| RabbitMQ | 消息量中等(百万级/天)、功能需求全面 | 需要水平扩展、吞吐量要求极高 |
| RocketMQ | 消息量大(千万级/天)、需要分布式部署 | 团队不熟悉Java生态、运维能力有限 |
经验总结
选型不是一步到位的。从简单方案开始,遇到瓶颈再升级,比一开始就上“重型武器”更务实。Redis List用了6个月,RabbitMQ用了2年,RocketMQ用了1年——每一步都比上一步撑得更久。
团队能力是重要的选型维度。功能再强大,运维不熟悉、排查问题困难,也会成为新的瓶颈。RocketMQ最终胜出的原因之一,是团队对Java技术栈的熟悉度远高于Erlang。
迁移成本需要考虑清楚。每次换型都需要改造代码、迁移数据、切换流量。不要轻易为了“技术先进”而换型,要为了“解决实际瓶颈”而换型。
消息队列的选型没有“最好”,只有“最合适”。每个阶段有每个阶段的需求,选择当时最合适的方案,等需求变化了再调整。
政策快报平台的实践是:从最简单的方案起步,在遇到瓶颈时果断评估是否到了该升级的节点,而不是过早追求“一步到位”或过晚才响应业务需求。