Pipeline 是 Redis 最便宜的加速手段,但它为什么有效、有多有效、又有什么不保证?这篇用一个可以加网络延迟的 TCP 代理,把同步与不同批量的管道放在不同 RTT 下比较,再验证它「不是事务」这件最容易被忽略的事。
RTT 同步(1 条/次) 管道 10 管道 100 管道 1000 (单位:条/秒) 0.0ms 38323 225045 529579 707164 1.0ms 566 5348 38379 200475 4.0ms 161 1587 14126 98351
同步请求的吞吐几乎被 RTT 卡死:RTT 1 ms 时只有 566 条/秒(约每条 1.8 ms),RTT 4 ms 时 161 条/秒。管道把一批命令放在一个往返里,批量越大越接近服务器自身的处理速度。批量 1000 时 RTT 从 0 增加到 4 ms,吞吐只从 707k 降到 98k。RTT 的模拟是我写的代理(每个方向固定延迟),不是真实网络:没有丢包、抖动。
A 共发了 20 个管道(每个 2000 条 INCR),B 读到 1250 次,其中 19 次读到的值不是 2000 的整数倍(即某个管道执行到一半);例如 [1780, 2890, 4890, 6890, 10890]
管道只是「把多条命令一起发出去」,服务器仍然一条一条执行,并且在管道的命令之间可以插入其它客户端的命令。B 读到 19 次「执行到一半」的值。需要原子性时用 MULTI/EXEC 或 Lua(第 29–38 篇)。
['OK', Err('WRONGTYPE Operation against a key holding the wrong kind of value'), 2, '2']回复严格按发送顺序返回;某条命令出错,只是它的回复是一个错误,后面的命令照常执行。客户端要逐条检查回复。