Redis Pipeline(管道):原理与最佳实践

Redis Pipeline 示意图

前言

Redis Pipeline(管道)是 Redis 中一种网络通信优化技术,它的核心思想是:

一次性发送多条命令,Redis 依次执行,然后再一次性返回所有结果。

这样可以显著减少客户端与 Redis 之间的网络往返(RTT,Round Trip Time)开销。

一、为什么会有 Pipeline

先看普通 Redis 请求。假设执行 4 条命令:

SET name tom
GET name
INCR counter
GET counter

正常情况下:

Client                 Redis

SET name tom  ------->

                执行

<------- OK


GET name ------->

              执行

<------- tom


INCR counter ------->

               执行

<------- 1


GET counter ------->

               执行

<------- 1

需要 4 次请求、4 次响应、4 次 RTT。如果 RTT 是 0.5ms,那么总耗时 ≈ 4 × 0.5ms = 2ms

假设有 10000 个命令,就是 10000 次 RTT。即使 Redis 本身执行只需几毫秒,网络时间 » Redis 执行时间,性能浪费严重。

二、Pipeline 的工作方式

Pipeline 出现后,客户端把命令一起发送:

Client ------------------------>
                Redis

SET name tom
GET name
INCR counter
GET counter

Redis 收到后按顺序执行(SET → GET → INCR → GET),执行完再统一返回:

<------------------------
OK
tom
1
1

整个过程只有 1 次发送、1 次接收、1 次 RTT

可以这样理解:

  • 普通模式:问一句、答一句,像聊天。
  • Pipeline:一次问 100 句,Redis 全部回答,像发邮件。

三、Pipeline 的本质

很多人误解:Pipeline 能让 Redis 并行执行命令。实际上不是——Redis 仍然是单线程执行命令:

SET a 1
SET b 2
SET c 3

Redis 内部仍然依次执行 SET aSET bSET c,没有并行。

Pipeline 优化的是网络往返时间(Network RTT),而不是命令执行时间

四、Pipeline 执行流程

以 5 条命令为例:

  1. 编码:客户端把所有命令编码(*3$3SET…)形成一个大 Buffer。
  2. 发送:一次 write()send(socket))发送给 Redis。
  3. 接收:Redis 从 socket buffer 收到 cmd1~cmd5。
  4. 解析执行:Redis 逐个解析并执行:
解析 cmd1 → 执行
解析 cmd2 → 执行
解析 cmd3 → 执行
...
  1. 缓冲结果:结果写入返回缓冲区(result1~result5)。
  2. 统一返回:一次返回给客户端,客户端再按顺序读取结果。

五、Pipeline 为什么快

举例:每次网络 RTT 为 0.2ms,Redis 执行一条命令 0.01ms,执行 10000 次 GET:

  • 普通模式10000 × (0.2 + 0.01) ≈ 2100 ms
  • Pipeline1 × RTT + 10000 × 0.01 ≈ 100 ms

性能提升 20 倍以上,甚至 50 倍、100 倍都很常见。

六、Pipeline 与 MGET 的区别

GET key1
GET key2
GET key3

为什么不用 MGET?

  • MGET:服务器命令优化,一次命令完成多个读取。
  • Pipeline:客户端网络优化,一次发送多个命令。

例如下面这些命令类型不同,MGET 做不到,但 Pipeline 可以:

GET user:1
HGET user:2 name
ZSCORE rank 100

七、Pipeline 与事务(Transaction)的区别

Pipeline 只是一起发送,例如:

SET a 1
INCR a
GET a

Redis 依次执行 SET、INCR、GET,中间可能被别的客户端插入命令

而事务:

MULTI

SET a 1
INCR a
GET a

EXEC

Redis 保证 EXEC 后整个命令队列连续执行,不会被其他客户端打断。

特性 Pipeline Transaction
减少 RTT
原子性
提升吞吐量 一般
防止插队

八、Pipeline 是否保证顺序

保证。例如:

SET a 1
INCR a
GET a

Pipeline 发送后,Redis 执行顺序一定是 SET → INCR → GET,返回结果 result1、result2、result3 也严格对应。

九、Pipeline 的缺点

1. 响应占用内存

假设 100 万条 GET,Redis 要缓存 100 万个结果才能统一返回,可能导致内存暴涨。所以通常按 100、500、1000、5000 一批,不要 100 万一批。

2. 无法实时拿结果

GET a

如果结果出来后才能决定:

SET b xxx

这种依赖关系不能 Pipeline,因为结果还没回来。

3. 某条命令失败不会回滚

SET a 1
INCR a
LPUSH a x

第三条报 WRONGTYPE 错误,但前两条已经执行成功,不会回滚

十、Pipeline 最佳实践

批量写适合 Pipeline:

SET user:1 ...
SET user:2 ...
SET user:3 ...

批量删适合 Pipeline:

DEL key1
DEL key2
DEL key3

批量缓存预热非常适合:

SET product:1 ...
SET product:2 ...
SET product:3 ...

批量查询也适合:

GET key1
GET key2
GET key3

十一、总结

Pipeline 是 Redis 提供的一种网络优化机制。客户端可以一次性向 Redis 发送多条命令,而不必等待每条命令的返回结果,Redis 按顺序执行这些命令后再批量返回结果。Pipeline 不会让 Redis 并行执行命令,也不保证原子性,它优化的是客户端与 Redis 之间的网络往返时间(RTT),因此在批量读写场景下可以显著提升吞吐量。实际生产中通常按几百到几千条命令分批使用 Pipeline,以避免响应结果过大导致内存压力。

一句话记忆:

Pipeline = Redis单线程不变
         + 批量发送命令
         + 减少RTT
         + 提高吞吐量