Redis 的 Pipeline 功能是什么?

Sherwin.Wei Lv7

Redis 的 Pipeline 功能是什么?

回答重点

Redis 的 Pipeline 功能允许客户端在一次网络请求中批量发送多个命令,以减少网络延迟并提高性能。通过将多个命令打包发送,客户端可以在不等待每个命令响应的情况下继续发送其他命令,从而显著提高吞吐量。

好处:

  • 节省了网络传输时间
  • 减少了 Redis 服务端上下文切换带来的开销

扩展知识

与事务的区别

  • Pipeline 并不保证命令的原子性,也不支持事务特性。如果某个命令失败,其他命令仍会继续执行。
  • Redis 的事务是通过 MULTI、EXEC 命令实现的,可以保证一组命令的原子性。

使用注意事项

需要注意 Pipeline 不宜包装过多的命令,因为会导致客户端长时间的等待,且服务器需要使用内存存储响应,所以官方推荐最多一次 10k 命令

image.png

还有一点需要注意 pipeline 命令执行的原子性不能保证,如果要保证原子性则使用 lua 脚本或者事务。

Pipeline 示例代码

Java 的 Jedis 库实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;

public class RedisPipelineExample {
public static void main(String[] args) {
// 创建 Redis 连接
Jedis jedis = new Jedis("localhost", 6379);

// 开始 Pipeline
Pipeline pipeline = jedis.pipelined();

// 批量设置键值对
for (int i = 0; i < 1000; i++) {
pipeline.set("key" + i, "value" + i);
}

// 执行所有命令
pipeline.sync();

// 关闭连接
jedis.close();
}
}

使用 Python 的 redis-py 库:

1
2
3
4
5
6
7
8
9
10
11
import redis

r = redis.StrictRedis(host='localhost', port=6379, db=0)
pipeline = r.pipeline()

for i in range(1000):
pipeline.set(f'key{i}', f'value{i}')

# 执行所有命令
pipeline.execute()

性能测试

使用 Pipeline 可以在性能测试中显著减少与 Redis 的交互延迟,适合在高负载情况下进行优化。

参考网络上的一个执行实验结果,使用 Pipeline 性能提升了 100 倍。

image.png

Pipeline 进一步分析

正常情况下,如果要执行多条命令,那么操作如下:

image.png

而 Redis pipeline(管道)使得客户端可以一次性将要执行的多条命令封装成块一起发送给服务端,具体过程如下图所示:

Redis 服务端在收到来自管道发送的多条命令之后,会先把这些命令按序执行,并将执行结果保存到缓存中,直到最后一条命令执行完成,再把命令执行的结果一起返回给客户端。

Redis 使用 pipeline 主要有以下两个好处:

1)节省了 RTT

RTT(Round Trip Time)即往返时间。Redis 客户端将要执行的多条指令一次性给服务端,显然减少了往返时间。

拿快递来理解,将所有快递都装进卡车在两地一次性配送和将快递分批装进面包车,多次往返两地送完快递。很显然一次性用卡车送完花在两地往返的时间最短。

2)减少了上下文切换带来的开销

当服务端需要从网络中读写数据时,都会产生一次系统调用,系统调用是非常耗时的操作。其中涉及到程序由用户态切换到内核态,再从内核态切换回用户态的过程。当我们执行 100 条 Redis 指令的时候,就发生 100 次用户态到内核态之间上下文的切换,但是如果使用管道的话,其将多条命令一同发送给服务端,就只需要进行一次上下文切换就好了,这样就可以节约性能。

Comments