bigywater.tech
RabbitMQ · 32

消息积压:原因排查与恢复

队列里 ready 一直涨,到底是没人消费、消费太慢、还是消费者卡住了?该看哪几个数?怎么最快清掉积压?这篇复现积压,对比三种情况的快照,并实测加消费者与 purge 的效果。

+438 条/秒
发布 800 条/秒而消费约 444 条/秒时,ready 的增长速度
159 → 1273
1 个与 8 个消费者的清积压吞吐(条/秒),线性增长
20 ms
purge 50000 条消息所需时间

怎么形成

实测 · 本机执行输出
  (秒, ready, unacked, consumers, consumer_capacity, 累计已处理): 
    (4, 1738, 10, 1, 0.051, 1775)
    (8, 3493, 10, 1, 0.007, 3543)
    (12, 5249, 10, 1, 0.005, 5323)
    (16, 7002, 10, 1, 0.004, 7101)
    (20, 8750, 10, 1, 0.005, 8878)
  发布 800 条/秒、消费约 444 条/秒:ready 以约 438 条/秒的速度增长;consumer_capacity 只有 0.005 上下:它表示队列能往消费者投递的时间占比,接近 0 说明消费者的 prefetch 窗口一直是满的——消费者就是瓶颈

发布速率超过消费速率,差值就是 ready 的增长速度。队列统计里的 consumer_capacity 接近 0 表示消费者的 prefetch 窗口始终是满的——消费者是瓶颈。

排查

实测 · 本机执行输出
  情形                              ready  unacked  consumers  consumer_capacity
  (a) 没有消费者                         5000        0          0               0.0
  (b) 1 个慢消费者 prefetch=10           4909       10          1             0.044
  (b2) 1 个慢消费者 prefetch=1000        3919     1000          1             0.044
  (c) 消费者卡住不 ack                    4900      100          1             0.043

看 consumers(0 说明没人消费)、messages_unacknowledged 是否等于 prefetch、ready 是否还在下降。慢和卡住的快照几乎一样,要看随时间的变化。

恢复

实测 · 本机执行输出
  消费者数  清空条数  耗时      吞吐
  1           4000    25.2 s      159 条/秒
  2          20000    62.9 s      318 条/秒
  4          20000    31.3 s      638 条/秒
  8          20000    15.7 s     1273 条/秒
  (1 个消费者只放了 4000 条,否则要几分钟;看吞吐:单个消费者的理论上限是 1 ÷ 5 ms = 200 条/秒,实测约 160 条/秒;吞吐随消费者数线性增长)

处理本身是瓶颈时,加消费者线性提高清积压速度:1 个 159 条/秒,8 个 1273 条/秒。

purge

实测 · 本机执行输出
  purge 50000 条: 返回 message_count=50000,用了 20 ms;purge 之后 ready=0

消息已无价值时,queue_purge 瞬间清掉所有 ready 的消息(50000 条 20 ms),不可逆。

分步演示

消息积压
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / RabbitMQ 4.3.6 / Erlang/OTP 28.5 / pika 1.4.4(Homebrew 与临时虚拟环境);所有节点都是本机自己起的 RabbitMQ 进程(127.0.0.1,端口 9500 以上,每个实验独立的数据目录与节点名,不连任何外部服务);命令输出来自真实的 rabbitmqctl 与管理 API,发布与消费用 pika 的真实连接;计时用 time.perf_counter,数字每次运行会有小幅抖动。第一节发布者用线程按固定间隔发,消费者每条 sleep 2 ms 模拟处理;第二节每种情形放 5000 条、等 4 秒再读;第三节每个消费者每条 5 ms、prefetch=20(1 个消费者只放了 4000 条);数字来自 rabbitmqctl list_queues,包括 consumer_capacity
    • 没有验证:消息体更大的积压对内存 / 磁盘的影响;积压到百万级时的恢复;消费者崩溃后重投造成的二次积压;死信 / 限流等减轻积压的策略;quorum 和 stream 队列上同样的指标;publisher 端用 reject-publish 做背压(第 13 篇)
    京ICP备2026067502号-1京公网安备11010502063487号