bigywater.tech
RabbitMQ · 13

队列长度限制与溢出策略

队列长度限制是保护 broker 的第一道防线,但“满了之后丢谁”“限制到底数什么”“quorum 队列也一样吗”都有细节。这篇在 RabbitMQ 4.3.6 上把每种溢出策略和计数口径都量一遍。

m5~m9
drop-head 上限 5、发 10 条后留下的消息——最老的 5 条被丢
0 条
单条 2000 字节、字节上限 1000 时留下的消息数
10 > 5
quorum 队列 reject-publish、上限 5,不开 confirm 连发 10 条后队列里的条数

drop-head

实测 · 本机执行输出
  队列里剩: ['m5', 'm6', 'm7', 'm8', 'm9']

默认策略:队列满了把队头(最老的)挤出去,留下最新的。没有通知,配了死信交换机时则变成 maxlen 死信(见死信那篇)。

reject-publish

实测 · 本机执行输出
  不开 confirm 发 10 条,队列里是: ['m0', 'm1', 'm2', 'm3', 'm4'](最先到的 5 条,后 5 条悄悄丢了)
  开 confirm 发 10 条的结果: ['ack', 'ack', 'ack', 'ack', 'ack', 'NACK', 'NACK', 'NACK', 'NACK', 'NACK']

满了拒绝新发布。开了 publisher confirm 的发布方收到 Nack;没开就悄悄丢。

reject-publish-dlx

实测 · 本机执行输出
  主队列: ['m0', 'm1', 'm2']
  死信队列: [('m3', 'maxlen'), ('m4', 'maxlen'), ('m5', 'maxlen')]
  对比 drop-head + 死信:主队列 ['m3', 'm4', 'm5'];死信队列(被挤出去的最老的)是 [('m0', 'maxlen'), ('m1', 'maxlen'), ('m2', 'maxlen')]

在拒绝新发布的同时把被拒绝的消息送进死信交换机,reason=maxlen。

按字节限制

实测 · 本机执行输出
  留下 10 条(100 字节/条,限制 1000 字节)
  同样的消息体再加上约 100 字节的头/属性:留下 10 条——限制只数消息体,不数属性
  单条 2000 字节(比限制大)发 3 条:留下 0 条

x-max-length-bytes 只数消息体,不数头和属性;比上限还大的单条消息留不下来。

参数与 policy

实测 · 本机执行输出
  max-length=10 且 max-bytes=500,发 20 条 100 字节:留下 5 条(字节限制先到)
  队列参数 x-max-length=10 + policy max-length=4,发 20 条:留下 4 条;policy 查询: ['/', 'lim', '^l6$', 'queues', '{"max-length":4}']

队列参数和 policy 同时给了长度限制,取较小的;和字节限制一起设,先到的生效。policy 的好处是可以不重建队列就改。

unacked 不算

实测 · 本机执行输出
  取走 3 条不 ack 后: (ready, unacked) = (0, 3)
  再发 10 条后: (ready, unacked) = (3, 3)(上限只管 ready 的)

已经投递出去等确认的消息不计入长度,所以 ready + unacked 可以超过上限。

quorum 队列

实测 · 本机执行输出
  quorum + drop-head(连发 10 条,上限 5):留下 ['m5', 'm6', 'm7', 'm8', 'm9']
  quorum + reject-publish,不开 confirm 连发 10 条(上限 5):留下 10 条
  quorum + reject-publish,开 confirm 每条间隔 10 ms 发 30 条的结果: AAAAAANNNNNNNNNNNNNNNNNNNNNNNN(A = Ack,N = Nack);队列里最后 6 条

drop-head 与经典队列一致;reject-publish 不精确:快速连发会超限,逐条 confirm 时也多收一条才开始 Nack。

分步演示

队列长度限制
本步的对象

    本文用到的工具与边界

    • 本机 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,数字每次运行会有小幅抖动。读队列内容用 basic_get 取空;第六节 (ready, unacked) 来自 rabbitmqctl list_queues;第七节 reject-publish 的 confirm 实验每条间隔 10 ms
    • 没有验证:policy 的 max-length 与 operator policy 的优先级;stream 队列的长度限制(用 retention,见第 17 篇);集群里 quorum 的限制精度在节点故障时;更大的消息、更高的并发下 quorum reject-publish 超出上限的幅度;x-max-length-bytes 在 quorum 队列上的口径
    京ICP备2026067502号-1京公网安备11010502063487号