azwcl
azwcl
Published on 2025-02-17 / 23 Visits
0
0

Redis 管道

1. 简介

1.1. 出现原因

  • Redis 是一种基于 C/S 模型以及 请求/响应 协议的 TCP 服务;一个请求遵循以下步骤:
    • C -> S 发送命令分四步:发送命令 -> 命令排队 -> 命令执行 -> 返回结果;并且监听 socket 返回,通常以阻塞模式等待服务端响应;
    • 服务端处理命令,并将结果返回给客户端;
  • 上述称之为:round tip time;简称:RTT;
  • 1693267867157.jpg
  • 如果同时需要执行大量的命令,那么就要等待上一条命令应答后再执行,这中间不仅仅多了RTT(Round Time Trip),而且还频繁调用系统 IO,发送网络请求,同时需要 redis 调用多次 read()write() 系统方法,系统方法会将数据从用户态转移到内核态,这样就会对进程上下文有比较大的影响了,性能不太好;

2.2. 解决思路

  • 如果可以一次性发送多条命令,然后一次性返回结果;岂不是完美;
  • 管道:可以一次性发送多条命令给服务端,等待服务端处理完成之后,会通过一次响应返回所有执行结果,减少客户端与 redis 的通信次数降低往返时间;pipeline 实现原理为队列,先进先出的特性保证数据的顺序性;

1693268134889.jpg

2. 管道

2.1. 管道定义

  • pipeline 为了解决 RTT 往返时间,仅仅是将命令打包一次发送,对于整个 redis 执行不造成其他的影响;
  • 一句话:批量处理命令的变种优化措施,类似于 redis 的远程批命令:mgetmset’;

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. 注意事项

  • 管道只是一次执行,不保证原子性,如果执行过程中指令有异常,那么依旧会执行后续的指令;
    • 如果有两个客户端:client1client2 ,那么同时向服务端发送管道,如果 管道包含 5 条命令;那么 redis 保证 client1 管道命令是顺序执行,client2 也是;但是不能保证 client1 执行完成后再执行 client2 ,可能是 client1client2 穿插执行的 ;
  • 使用管道组装的命令个数不可太多,不然数据量过大,客户端阻塞时间可能过久,同时服务端此时也被迫回复一个队列答复,占用很多内存;其发送的命令虽然不会北限制,但是输入缓存区大小为 1GB;如果超过限制,那么命令不会执行,且被服务端断开链接;少部分客户端自己本身也有缓存区大小的设定,需注意;

Comment