Skip to content

Redis管道(pipeline)

1. 问题背景

Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。一个请求会遵循以下步骤:

  1. 客户端向服务端发送命令分四步(发送命令→命令排队→命令执行→返回结果),并监听Socket返回,通常以阻塞模式等待服务端响应。
  2. 服务端处理命令,并将结果返回给客户端。
    上述两步称为:Round Trip Time(简称RTT,数据包往返于两端的时间)
    命令执行流程图 如果同时需要执行大量的命令,那么就要等待上一条命令应答后再执行,这中间不仅仅多了RTT(Round Time Trip),而且还频繁调用系统IO,发送网络请求,同时需要redis调用多次read()和write()系统方法,系统方法会将数据从用户态转移到内核态,造成上下文频繁切换,这样频繁命令往返势必会造成Redis的性能瓶颈。

2. 管道概述

管道(pipeline)可以一次性发送多条命令给服务端,服务端依次处理完完毕后,通过一条响应一次性将结果返回,通过减少客户端与edis的通信次数来实现降低往返延时时间。pipeline实现的原理是队列,先进先出特性就保证数据的顺序性。类似Redis的原生批命令(比如mgetmset), 区别是管道支持不同数据类型的批处理。 管道执行流程图

3. 管道的使用

sh
[root@hadoop105 bin]# cat /tmp/pipline.txt
ping
lpush mylist a b c d e f 123 45
hset mymap name jack age 33
sadd myset1 ff gg jj 44 12
set pass pass123
zadd myzset1 10 bike 100 motor 800 car 2000 plane
setbit mybitmap 1 1
setbit mybitmap 365 1
pfadd ip.log 192.168.101.1 127.0.0.1 192.168.101.101 127.0.0.1
geoadd city_pos 104.100227 30.675702 电子科技大学 104.077774 30.655544 春熙路
xadd mystream1 * id 123 name jack
dbsize
[root@hadoop105 bin]# cat /tmp/pipline.txt |  ./redis-cli -a jack --raw --pipe
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 12

4. 管道的总结

4.1 管道和原生批量命令对比

  1. 原生批量命令是原子性⚛️(例如:mset,mget),pipeline是非原子性
  2. 原生批量命令一次只能执行一种命令,pipeline支持批量执行不同命令。
  3. 原生批命令是服务端实现,而pipeline需要服务端与客户端共同完成。

4.2 管道和Redis事务的对比

  1. 事务具有原子性,管道不具有原子性
  2. 管道一次性将多条命令发送到服务器,事务是一条一条的发,事务只有在接收到会执行管道不会。
  3. 执行事务时会阻塞其他命令的执行,而执行管道中的命令时不会。

4.3 注意事项

  1. pipeline缓冲的指令只是会依次执行,不保证原子性,如果执行中指令发生异常,将会继续执行后续的指令。
  2. 使用pipeline组装的命令个数不能太多,不然数据量过大客户端阻塞的时间可能过久,同时服务端此时也被迫回复一个队列答复,占用很多内存。