知其然,知其所以然
RabbitMQ 内部原理 2026-10-13

队列长度限制与溢出策略

在 RabbitMQ 4.3.6 上实测队列长度限制:drop-head 丢最老的、reject-publish 丢新的并在有 confirm 时 Nack、reject-publish-dlx 把新的死信;x-max-length-bytes 只数消息体;参数与 policy 取较小的;unacked 不计入;quorum 队列的 reject-publish 连发时会超限(连发 10 条全留下,上限 5)。

RabbitMQ 队列长度限制 x-max-length overflow drop-head reject-publish 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

惰性队列(lazy)与内存

在 RabbitMQ 4.3.6 上实测惰性队列:x-queue-mode=lazy 仍被接受但与默认经典队列在内存上看不出区别(都是 messages_ram≈1,100000 条 1 KB 只增 1~1.3 MiB);quorum 队列同样数据让 broker 总内存增加 166.3 MiB;消费时内存随投递窗口走;重启 11.1 s 后消息按需读盘。

RabbitMQ 惰性队列 lazy 内存 classic queue quorum 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

quorum 队列与经典镜像队列的区别

在 3 节点 RabbitMQ 4.3.6 集群上对比 quorum 队列和经典队列:ha-mode 策略已被移除(set_policy 失败,classic_queue_mirroring=removed);kill -9 队列所在节点后,quorum 队列 303 ms 就能继续发布且不丢数据,经典队列要等 66.6 s 超时;本机回环上 3 副本与单副本的吞吐几乎一样。

RabbitMQ quorum队列 镜像队列 ha-mode 集群 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

quorum 队列的 Raft:选主与写入路径

在 3 节点 RabbitMQ 4.3.6 集群上看 quorum 队列的 Raft:quorum_status 里的 Term 与日志下标;发布 1000 条后三成员下标一致;杀掉 leader 360 ms 内选出新 leader(Term 1→2);只剩 1/3 成员时发布一直挂起、basic_get 报 541;恢复后挂起的发布得到 ack,1002 条一条不丢;3 副本比 1 副本慢约 19%。

RabbitMQ quorum队列 Raft 选举 多数派 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

stream 队列:追加日志与偏移

在 RabbitMQ 4.3.6 上用 AMQP 客户端验证 stream 队列:消息读完不删,多个消费者各从自己的 offset 读;x-stream-offset 的 first / last / next / 数字 / 时间戳;basic_get、自动确认、非持久、exclusive 都不支持;按段保留(限制 20 MB 后最老的 44778 条之前被整段删除);消费吞吐与 classic 相当。

RabbitMQ stream队列 offset 追加日志 保留策略 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

集群:节点、元数据与队列所在节点

在 3 节点 RabbitMQ 4.3.6 集群上实测:元数据在所有节点上(Khepri 存储),消息只在队列所在节点;连别的节点发布 p50 多 0.036 ms;client-local 把队列放在声明它的节点,balanced 策略让 9 个队列均分;停掉的节点仍是成员,要 forget_cluster_node;cookie 不一致只报 noconnection;只剩 1/3 节点时已有队列照常收发、新建队列卡住。

RabbitMQ 集群 Khepri 元数据 queue-leader-locator forget_cluster_node 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

网络分区处理策略

在 3 节点 RabbitMQ 4.3.6 集群上真实隔离一个节点:多数派侧能建新队列、quorum 队列选出新 leader 继续写;少数派侧元数据写和 quorum 写都挂起,但本地经典队列照常;愈合后自动恢复且 Network Partitions 为空、分区期间的本地消息保留;pause_minority 在这里没有让少数派节点拒绝连接。

RabbitMQ 网络分区 partition handling pause_minority Khepri 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

流控(flow control)与内存、磁盘水位告警

在 RabbitMQ 4.3.6 上实测流控:内存水位线按 RSS 计算,超限后发布连接 blocking→blocked、客户端收到 Connection.Blocked(low on memory),消费者读走消息后收到 Unblocked;磁盘告警在这台 macOS 上读不到剩余空间无法验证;4 个全速发布者采样 800 次全是 running,没有观察到 flow。

RabbitMQ 流控 内存水位线 Connection.Blocked credit flow 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

连接与 channel 的数量:一个连接多少 channel 合适

在 RabbitMQ 4.3.6 上实测连接与 channel 的数量:channel_max 默认 2047,开到上限后再开失败;每个 channel 约 4 个 Erlang 进程、20 KiB 左右;一条连接上 1~64 个 channel 的发布吞吐没有变化(约 37000 条/秒);多连接才能提高总吞吐(1 个 36805 → 4 个 94976 条/秒)。

RabbitMQ 连接 channel channel_max 吞吐 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

心跳与连接断开检测

在 RabbitMQ 4.3.6 上实测心跳:默认 60 秒,客户端请求 0/5/30/120 都被采用;heartbeat=2 时双方每秒各发一个 8 字节的 Heartbeat 帧;网络黑洞下 broker 约 6.1 秒(3 倍超时)才发现;heartbeat=0 的黑洞 25 秒后连接仍在;pika 的 BlockingConnection 线程忙 8 秒就会被 broker 踢掉。

RabbitMQ 心跳 heartbeat 连接断开检测 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

自动重连与拓扑恢复

在 RabbitMQ 4.3.6 上对比客户端的断线行为:pika 的 BlockingConnection 被强制关闭后抛 ConnectionClosedByBroker 且不恢复;aio-pika 的 connect_robust 在 broker 重启(6 秒中断)后自动重连并恢复消费者,728 条无重复无丢失,但停机期间发布端有 510 次失败要自己重试;队列被删时只收到 Basic.Cancel。

RabbitMQ 自动重连 拓扑恢复 aio-pika connect_robust 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

消费者超时:consumer_timeout

在 RabbitMQ 4.3.6 上验证 consumer_timeout:默认 1800000 ms,rabbitmq.conf 改成 10000 后 eval 读到 {ok,10000};x-consumer-timeout 队列参数经典队列返回 406、quorum 队列成功,policy consumer-timeout 可设;但把超时配成 10 s、消费者收到消息不确认,等 7 分钟 channel 没有被关——原因没查清,如实记录。

RabbitMQ consumer_timeout 消费者超时 未确认 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号