1. 简介
1.1. 出现原因
- Redis 是一种基于 C/S 模型以及 请求/响应 协议的 TCP 服务;一个请求遵循以下步骤:
- C -> S 发送命令分四步:发送命令 -> 命令排队 -> 命令执行 -> 返回结果;并且监听 socket 返回,通常以阻塞模式等待服务端响应;
- 服务端处理命令,并将结果返回给客户端;
- 上述称之为:round tip time;简称:RTT;

- 如果同时需要执行大量的命令,那么就要等待上一条命令应答后再执行,这中间不仅仅多了RTT(Round Time Trip),而且还频繁调用系统 IO,发送网络请求,同时需要 redis 调用多次
read()
和 write()
系统方法,系统方法会将数据从用户态转移到内核态,这样就会对进程上下文有比较大的影响了,性能不太好;
2.2. 解决思路
- 如果可以一次性发送多条命令,然后一次性返回结果;岂不是完美;
- 管道:可以一次性发送多条命令给服务端,等待服务端处理完成之后,会通过一次响应返回所有执行结果,减少客户端与 redis 的通信次数降低往返时间;
pipeline
实现原理为队列,先进先出的特性保证数据的顺序性;

2. 管道
2.1. 管道定义
pipeline
为了解决 RTT 往返时间,仅仅是将命令打包一次发送,对于整个 redis 执行不造成其他的影响;
- 一句话:批量处理命令的变种优化措施,类似于 redis 的远程批命令:
mget
和 mset
’;
2.2. 实操
# ls
command.txt dump.rdb
# cat command.txt
set k1 v50
set k2 v20
hset map name azwcl
# cat command.txt | redis-cli --pipe
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 3
4. 总结
4.1. 管道 与 原生批量命令对比
- 原生批量命令是原子性的;管道是非原子性的;
- 原生批量命令一次只可以执行一种命令,管道是支持执行不同命令;
- 原生批量命令是服务端实现,管道是客户端和服务端共同完成;
4.2. 管道 与 事务对比
- 事务具有原子性,管道无;
- 管道一次性将多条命令发送到服务器端,事务是一条条发,只有接收到
EXEC
命令才会执行;
- 执行事务时,会阻塞其他命令执行,但是执行管道中命令时不会;
4.3. 注意事项
- 管道只是一次执行,不保证原子性,如果执行过程中指令有异常,那么依旧会执行后续的指令;
- 如果有两个客户端:
client1
和 client2
,那么同时向服务端发送管道,如果 管道包含 5 条命令;那么 redis 保证 client1
管道命令是顺序执行,client2
也是;但是不能保证 client1
执行完成后再执行 client2
,可能是 client1
和 client2
穿插执行的 ;
- 使用管道组装的命令个数不可太多,不然数据量过大,客户端阻塞时间可能过久,同时服务端此时也被迫回复一个队列答复,占用很多内存;其发送的命令虽然不会北限制,但是输入缓存区大小为 1GB;如果超过限制,那么命令不会执行,且被服务端断开链接;少部分客户端自己本身也有缓存区大小的设定,需注意;