双十一期间订单量暴增,实时数据同步系统出现消息堆积,如何应对?
- 标签:后端、场景题
🏛 业务架构师
双十一订单暴增导致同步链路消息堆积——我的答案分事中应急和事前容量两半,并且先明确处理原则:堆积本身不可怕,可怕的是核心链路被堆积拖垮和恢复时的二次冲击。
事中应急(按顺序执行)
- 分级保命:确认堆积的是哪些 topic——支付、订单核心链路的堆积优先处理,日志、通知类直接丢弃或转储(DLQ 暂存后补)——业务分级决定资源投向
- 扩容消费者:加消费者实例提升并行度,但注意分区数是并行度上限(Kafka 20 个分区,100 个消费者也没用)——此时要做消费者内部多线程或紧急扩分区(扩分区会破坏 key 有序性,需评估影响面)
- 消费端提速:批量拉取、批量写库、跳过非必要处理步骤(复杂转换降级为简单透传,事后补算)——降级处理逻辑换吞吐
- 转储削峰:把堆积消息快速搬到廉价存储(对象存储/临时表),消费端按目标端能力匀速回放——先保护数据不丢,再谈处理
- 源头限流:极端情况通知业务侧降低非核心消息生产(关闭部分埋点、通知)
恢复期防护(容易被忽略)
堆积消化后下游会迎来持续高压:写库前限速、目标端(数仓/ES)的写入压力监控——恢复太快打挂数仓就是二次事故。
事前容量建设(架构师重点)
- 大促容量规划:预估峰值(去年 × 增长率 × 1.5 冗余),压测验证同步链路极限吞吐
- 弹性扩容预案:消费者 Pod 混部资源池、一键扩容脚本——应急能力平时演练
- 常态化水位监控:堆积量、消费延迟(Lag)告警分级——Lag 涨 10 分钟就告警,别等半小时才发现
收尾:堆积问题的本质是产能规划问题:大促流量可预测,同步链路的容量也该可规划。事前压测的钱,远比事中全員救火便宜。
🏗 系统架构师
大促期间消息堆积,我的处理框架是**"保核心、扩消费、控源头、可回溯"**四步,先止损再扩容。
第一步:快速定位堆积原因(决定动作方向)
- 监控看消费 TPS 与生产 TPS 曲线:生产暴涨(订单洪峰)还是消费掉了(消费报错、下游变慢)?
- 消费者日志看是否在疯狂重试(某条毒消息卡住整条队列)、下游 DB/接口是否变慢
- 看堆积分布:全分区堆积(下游能力问题)还是单分区(倾斜/单 key 热点)
第二步:扩消费能力(最直接的止损)
- 消费者实例水平扩容,但上限是分区数(Kafka 一个分区同一消费组内只能被一个消费者消费)——分区数预留不足是容量规划失误,大促前要预估:峰值 TPS × 消费延迟容忍 → 分区数 = 峰值生产速率 / 单消费者速率 × 余量
- 提升单实例并行度(消费线程池),处理逻辑异步化(收到即 ACK,处理异步 + 手动位移管理要谨慎,改成"处理完再提交")
- 下游同步扩容:消费慢往往因为写数仓慢,Doris 扩、批次调大、compaction 资源倾斜给写入
第三步:分级降级(扩容来不及/无效时)
- 按消息重要性分级:支付/订单状态消息必须消费;埋点、推荐、报表类降级丢弃或转存(直接落到对象存储,事后离线回放)——丢的只是实时性,不丢数据
- 消费逻辑内降级:去掉非必要操作(去重查询、关联维表),轻量化跑
第四步:源头与事后
- 源头限流:生产端(业务侧)对非核心消息限流/降级
- 堆积期间的位点管理与告警:堆积量、最老消息年龄两个指标,超过保留期的消息会被清理——堆积逼近 retention 时间是最危险的信号,提前扩磁盘或提高 retention
- 事后复盘补三件事:容量模型修正(大促流量系数)、常态压测、自动扩容预案(堆积阈值触发)
一句话:先判断消费端病根,分区上限内扩容,分级丢卒保车,绝不无脑加机器。
💻 全栈开发专家
大促消息堆积,我分紧急止血 → 恢复 → 根治三段处理,先保数据不丢、再追平、最后补容量课。
紧急止血(10 分钟内)
- 横向扩消费者:K8s 把消费者 Deployment 扩到分区数上限(Kafka 消费者数超过分区数就浪费,先对齐这个数);分区不够先扩分区(注意 key 顺序性受影响,订单类 topic 慎重)。
- 消费逻辑降级:非关键旁路动作(发积分、埋点)先摘掉,只保主链路落库;批量写代替逐条写(每批几百条一次 commit)。
- 跳过策略:堆积的是可重算数据(如缓存预热消息),直接重置 offset 到最新,事后离线补算,别让实时链路陪葬。
恢复期(小时级)
- 旁路卸载:写个"搬运工"消费者把消息快速转存到本地盘/对象存储,让线上消费位点先追上,转存数据慢慢回放。
- 隔离毒丸:个别消息反复失败导致无限重试拖慢整体,重试超限直接进死信,人工处理,不阻塞队列。
- 盯 consumer lag 曲线和分区倾斜:某个分区堆积多半是某条慢消息或数据倾斜,单独处理。
根治(大促后)
- 容量压测:按双 11 峰值 3 倍压测消费能力,提前扩分区和消费者。
- 消费提效:改批量 + 异步 IO + 虚拟线程并行调用下游,单消费者吞吐通常能翻几倍。
- 分级 topic:核心(订单)和非核心(通知)分开,非核心允许丢弃/降级。
- 告警前移:lag 超过 5 分钟消费量即告警,别等堆积百万条才发现。
一句话:堆积的本质是消费速度 < 生产速度,所有手段都是在"提消费、降生产、换时间"里选。