bigywater.tech
RabbitMQ · 27

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

事务模式和确认模式都能让发布者知道消息“收下了”,该选哪个?事务到底多慢,它多出来的“原子性”有什么用?这篇用线上帧、回滚和吞吐实测对比。

4436 vs 51929
事务每条提交与异步 confirm 的吞吐(条/秒)
Tx.Commit
提交前别的连接看到 0 条,提交后 3 条一起可见
0.193 vs 0.162 ms
单条消息提交的 p50 延迟:事务与 confirm

事务

实测 · 本机执行输出
  提交之前别的连接看到队列 tq 里有 0 条
  C→S  ch1  Tx.Select         12 字节
  S→C  ch1  Tx.SelectOk       12 字节
  C→S  ch1  Basic.Publish     19 字节
  C→S  ch1  ContentHeader     23 字节
  C→S  ch1  ContentBody       10 字节
  C→S  ch1  Basic.Publish     19 字节
  C→S  ch1  ContentHeader     23 字节
  C→S  ch1  ContentBody       10 字节
  C→S  ch1  Basic.Publish     19 字节
  C→S  ch1  ContentHeader     23 字节
  C→S  ch1  ContentBody       10 字节
  C→S  ch1  Tx.Commit         12 字节
  S→C  ch1  Tx.CommitOk       12 字节
  提交之后队列 tq 里有 3 条

Tx.Select 之后的发布、确认在 Tx.Commit 之前对别人不可见,Tx.Rollback 丢弃。一个事务可以跨多个队列。

性能

实测 · 本机执行输出
  发布 3 条后 rollback:tq 里有 0 条
  一个事务里往两个队列各发一条并提交:tq 1 条、tq2 1 条
  事务里的消费确认也能回滚:
    取一条并 ack 后 tx_rollback:tq (ready, unacked) = (0, 1)(ack 被撤销,消息仍是未确认,回滚不会让它回到 ready;关闭 channel 后才回队列)
    关闭连接后: (1, 0)

事务每条都提交时只有 4436 条/秒,比同步 confirm 慢;批量提交(每 100 条)升到 29985 条/秒。异步 confirm(窗口 1000)是最快的方式,51929 条/秒。

延迟

实测 · 本机执行输出
  方式                      耗时      吞吐
  事务,每条提交                   1127 ms      4436 条/秒
  事务,每 10 条提交                265 ms     18849 条/秒
  事务,每 100 条提交               167 ms     29985 条/秒
  事务,每 1000 条提交              159 ms     31410 条/秒
  confirm,同步逐条等              875 ms      5712 条/秒
  confirm,异步窗口 1000           96 ms     51929 条/秒
  不确认(阻塞)                    138 ms     36229 条/秒

单条消息提交的 p50:事务 0.193 ms,confirm 0.162 ms,差别很小。

选择

实测 · 本机执行输出
  事务 publish+commit:p50 0.193 ms,p99 0.300 ms
  confirm publish+等 ack:p50 0.162 ms,p99 0.269 ms

追求吞吐和一般的“送达”确认用 publisher confirm;只有需要“多条消息(或多个队列)要么都可见要么都不可见”的场景才用事务。

分步演示

事务与确认
本步的对象

    本文用到的工具与边界

    • 本机 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,数字每次运行会有小幅抖动。线上帧经自己写的 TCP 代理;吞吐是 5000 条 100 字节持久化消息到持久队列,各方式 3 轮中位数;前面事务和同步 confirm 用 pika BlockingConnection,异步 confirm 用 SelectConnection(客户端类型不同,不能直接解读为“confirm 比不确认更快”);延迟各 2000 次
    • 没有验证:quorum 队列上的事务行为;事务中途连接断开时的状态;事务里消息很大时的内存;事务与 mandatory 的组合;生产环境磁盘上的延迟(macOS 笔记本,fsync 不等于落盘)
    京ICP备2026067502号-1京公网安备11010502063487号