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

消息幂等:重复投递的来源与去重

在 RabbitMQ 4.3.6 上复现两种重复来源:消费者 ack 前崩溃导致重复处理(redelivered=True)、发布端因 Ack 丢失而重发导致队列里 2 份(都是 redelivered=False);broker 不会按 message_id 去重;用 message_id 唯一约束 + 同事务让 1100 次投递只执行 1000 次,余额 1000;100 万个 message_id 约 28.3 MiB。

RabbitMQ 幂等 重复投递 message_id 至少一次 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

消息顺序:多消费者下顺序怎么保持

在 RabbitMQ 4.3.6 上实测保序:单队列单消费者严格有序;多消费者并发会打乱完成顺序(2/4/8 个消费者总逆序对 68/298/468);prefetch=10 下被 nack 并 requeue 的消息会被推迟到已预取的之后;按 key 分区到 8 个队列后,100 个账户内部顺序 0 个乱序。

RabbitMQ 消息顺序 多消费者 requeue 按key分区 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

事务模式与确认模式的性能对比

在 RabbitMQ 4.3.6 上对比事务模式与确认模式:事务提交前消息不可见、可跨队列原子提交、可回滚;5000 条持久化消息,事务每条提交 4436 条/秒、每 100 条提交 29985 条/秒,confirm 同步 5712 条/秒、异步窗口 51929 条/秒;单次延迟 p50 事务 0.193 ms 对 confirm 0.162 ms。

RabbitMQ 事务 tx publisher confirm 吞吐 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

消息大小对吞吐的影响

在 RabbitMQ 4.3.6 上实测消息大小的影响:10 B~1 KiB 约 5~6 万条/秒,100 KiB 起带宽到约 1.4 GiB/秒;classic 与 quorum 在单节点上几乎重合;300 KiB 消息拆成 3 个 ContentBody 帧(frame_max 131072);max_message_size 16 MiB,17 MiB 被 406 拒绝;1000 条 1 MiB 消息只让 RSS 涨 15 MiB、磁盘涨 1000 MiB。

RabbitMQ 消息大小 吞吐 frame_max max_message_size 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

RPC 模式:reply_to 与 correlation_id

在 RabbitMQ 4.3.6 上实测 RPC 模式:reply_to + correlation_id 的线上帧;两个速度不同的服务端使响应乱序到达,靠 correlation_id 对应;每次新建回复队列 p50 3.317 ms,复用回复队列 0.257 ms,direct reply-to 0.237 ms;服务端不在线时客户端要自己超时,带 expiration 的请求会被队头挡住。

RabbitMQ RPC reply_to correlation_id direct reply-to 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

Shovel 与 Federation

在两个 RabbitMQ 4.3.6 节点上实测 Shovel 和 Federation:动态 shovel 把 1000 条消息从 A.src 搬到 B.dst,三种 ack-mode 约 2 万条/秒;目的端宕机时 shovel terminated、消息留在源队列,恢复后 0.4 s 搬完;交换机联邦按下游绑定复制消息(5/6 条);队列联邦只在下游有消费者时才把消息搬过来。

RabbitMQ Shovel Federation 跨集群 联邦 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

管理 API 与监控指标

在 RabbitMQ 4.3.6 上实测监控接口:管理 API 的统计每 5000 ms 收集一次,发布 1000 条后 7.7 秒才在 API 里看到(rabbitmqctl 立即可见);publish rate 稳定显示 200.0 但 messages 滞后数秒;Prometheus /metrics 一次 1689 行、抓取 16 ms;macOS 上 fd/socket/disk_free 读不到;管理插件的开销在噪声内。

RabbitMQ 管理API 监控 Prometheus collect_statistics_interval 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

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

在 RabbitMQ 4.3.6 上复现消息积压:发布 800 条/秒、消费约 444 条/秒时 ready 每秒增长约 438 条,consumer_capacity≈0.005 表示消费者是瓶颈;无消费者 / 慢消费者 / 卡住消费者的快照对比;加消费者 1→8 个吞吐 159→1273 条/秒线性增长;purge 50000 条只要 20 ms。

RabbitMQ 消息积压 consumer_capacity prefetch 清积压 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

TTL:消息 TTL 与队列 TTL 的过期时机

在 RabbitMQ 4.3.6 上实测 TTL:1000 ms 的消息约 1 秒整批过期;队头没过期时后面过期的 10 条变成“僵尸”(ready 仍是 11);队列 TTL 与消息 TTL 取较小;expiration=0 表示立即投递否则丢弃;x-expires 的队列无人使用约 3 秒后删除,passive 声明也算使用;TTL 按发布时刻计,重启后已过期的消息不再出现。

RabbitMQ TTL 消息过期 x-expires 队头阻塞 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

与 Kafka 对比:同一场景下的吞吐与延迟

在同一台机器上对比 RabbitMQ 4.3.6 与 Kafka 4.3.1:发布 10 万条 100 字节,RabbitMQ 异步 confirm 61155 条/秒,Kafka 150 万~210 万条/秒(客户端不同,仅看数量级);低速率 p50 延迟 0.60 vs 0.34 ms;扇出给 3 个下游时磁盘 174 vs 49 MiB;RabbitMQ 经典队列读完即删而 Kafka 可从头重放。

RabbitMQ Kafka 对比 吞吐 延迟 扇出 重放 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

Outbox 模式:数据库和消息的一致

用 sqlite + RabbitMQ 4.3.6 复现并解决双写问题:先写库再发消息会丢消息(1000 单丢 58 条);Outbox 模式(订单与待发送事件同事务,relay 轮询发布)不丢但重复 60 条,至少一次;配合下游去重业务只执行 1000 次;relay 延迟约等于 poll 间隔,批量标记把吞吐从 2852 提到 5471 行/秒。

RabbitMQ Outbox 事务 双写 最终一致 真实验证 动画演示
RabbitMQ 内部原理 2026-10-13

消费者崩溃后未确认消息的重新投递

在 RabbitMQ 4.3.6 上实测消费者崩溃后未确认消息的重新投递:kill -9 后 381 ms 回队列;确认过的不重投、未确认的回到队首且 redelivered=True;网络黑洞靠心跳 8.6 s 才回队列;quorum 队列有 x-delivery-count 和 x-delivery-limit(重投 3 次后丢弃),经典队列只有 redelivered 布尔值。

RabbitMQ 未确认 重新投递 redelivered x-delivery-count delivery-limit 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号