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 等原生批量时优先用原生批量。