bigywater.tech
Redis · 102

Redis Pipeline 原理

Pipeline 是 Redis 最便宜的加速手段,但它为什么有效、有多有效、又有什么不保证?这篇用一个可以加网络延迟的 TCP 代理,把同步与不同批量的管道放在不同 RTT 下比较,再验证它「不是事务」这件最容易被忽略的事。

354 倍
RTT 1 ms 时管道(1000 条/批)相对同步的吞吐:200k vs 566 条/秒
611 倍
RTT 4 ms 时的同一比值(98k vs 161)
不是事务
另一个客户端 19 次读到了管道执行一半时的中间值

RTT 与吞吐

每格 3 次取中位;RTT 0 的每格 20000 条,有延迟的每格 5000 条(RTT>0 的同步只写 2000 条)
实测 · 本机执行输出
     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']

回复严格按发送顺序返回;某条命令出错,只是它的回复是一个错误,后面的命令照常执行。客户端要逐条检查回复。

分步演示:为什么管道快

Redis Pipeline 原理
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Redis 8.10.2 独立实例(本机回环端口,save 关闭),redis-cli 风格输出由自写的 RESP 客户端打印;计时用 time.perf_counter,数字每次运行会有小幅抖动。延迟由自写的 DelayProxy 加在两个方向(TCP_NODELAY);单客户端;SET 命令
    • 没有验证:真实网络的抖动与丢包、多客户端并发时的叠加、管道过大对服务器内存与其它客户端延迟的影响(第 103 篇)
    京ICP备2026067502号-1京公网安备11010502063487号