事务模式和确认模式都能让发布者知道消息“收下了”,该选哪个?事务到底多慢,它多出来的“原子性”有什么用?这篇用线上帧、回滚和吞吐实测对比。
提交之前别的连接看到队列 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;只有需要“多条消息(或多个队列)要么都可见要么都不可见”的场景才用事务。