Redis 管道 Pipeline

一次命令交互至少花费一个网络往返(RTT),执行 1000 条独立命令就要 1000 次往返,时间大多耗在网络上而非 Redis 本身。管道(Pipeline)把多条命令一次性发给服务器、再一次收齐全部结果,把 N 次往返压缩成 1 次,是客户端吞吐优化的第一手段。

原理:一次往返发一批

普通模式:SET → 等结果 → GET → 等结果……每步一个 RTT;管道模式:客户端一次写出整批命令,服务器顺序执行并按序返回结果。假设 RTT 为 1ms、单条命令服务端耗时 0.1ms,1000 条命令逐个执行约 1 秒以上,管道后约 0.1~0.2 秒量级——网络越远(如跨机房)收益越大。

用 redis-cli --pipe 体验

把命令写进文件,用 --pipe 一次性灌入:

cat > cmds.txt <<'EOF'
SET k1 v1
SET k2 v2
GET k1
EOF
redis-cli --pipe < cmds.txt
# 输出:All data transferred. Waiting for the last reply...
# 输出:Last reply received from server.
# 输出:errors: 0, replies: 3

验证结果:

MGET k1 k2
# 输出:1) "v1"
#       2) "v2"

redis-benchmark 加 -P 参数可直观感受管道对吞吐的提升:

redis-benchmark -t set -n 100000 -P 16 -q
# 输出:SET: xxx requests per second(数值随机器与网络变化,远大于不加 -P 时)

与原生批量命令的对比

很多需求原生命令一次就能完成,根本用不上管道:

MSET a 1 b 2 c 3
# 输出:OK
MGET a b c
# 输出:1) "1"
#       2) "2"
#       3) "3"

MSET/MGET、DEL 多 key、EXISTS 多 key 等原生批量适合"同类型操作",且(如 MSET)是原子的;管道适合"异构命令序列、需按结果拼装"的场景,但不保证原子。

注意事项

  • 管道不保证原子性:批中某条失败不影响其他命令;要原子就整批包进 MULTI/EXEC 或用 Lua。
  • 一次塞太多会占满客户端与服务端的内存缓冲,建议分批(每批几百到几千条)。
  • 返回结果要按顺序一次性读完,读得慢会让服务端发送缓冲写满、造成阻塞。
  • 管道是单连接行为,集群模式下跨节点的命令无法放进同一条管道,需按节点分组。
  • 可与事务叠加:把 MULTI……EXEC 整段作为命令写进管道,即可批量提交事务。

小结

管道通过"一次往返、批量收发"摊薄 RTT 开销,是 Redis 客户端提速的首选手段。记住三点:省的是网络耗时而非服务端耗时、不保证原子性、注意分批防内存膨胀;能用 MSET 等原生批量时优先用原生批量。

笔记加载中…