Redis中的管道Pipeline操作
点击上方蓝色字体,选择“设为星标”
Redis默认每次执行请求都会创建和断开一次连接池的操作,如果想执行多条命令的时候会在这件事情上消耗过多的时间,因此我们可以使用Redis的管道来一次性发送多条命令并返回多个结果,节约发送命令和创建连接的时间提升效率。
介绍
在前面我们介绍过Redis的事务和lua脚本操作,事实上在各语言版本的Redis中都有管道(Pipeline)的功能,本篇以python版作为示例,当我们使用python给redis发送命令时会经历下面的步骤:
客户端发送请求,获取socket,阻塞等待返回;
服务端执行命令并将结果返回给客户端;
而当执行的命令较多时,这样的一来一回的网络传输所消耗的时间被称为RTT(Round Trip Time),显而易见,如果可以将这些命令作为一个请求一次性发送给服务端,并一次性将结果返回客户端,会节约很多网络传输的消耗,可以大大提升响应时间。
官网:https://redis.io/topics/pipelining
逐个命令请求:
管道请求:
使用
管道的使用很简单,python版代码如下,在管道中可以选择是否开启事务,默认是开启的,这里的事务与Redis的事务一样为弱事务性不是真正的事务:
import redis
#创建连接池获取连接
pool = redis.ConnectionPool(host='wykd', port=6379,password='123456', decode_responses=True)
rp1 = redis.Redis(connection_pool=pool)
#创建管道,可以选择开启或关闭事务,这里的事务与Redis事务一样是弱事务型
pipe = rp1.pipeline(transaction=True)
#在管道中添加命令
pipe.set('new','123')
pipe.set('name', 'wyk2')
pipe.set('company', 'csdn2')
pipe.hincrby('hage','wyk',1)
#这个命令会报错,因为hage为hash类型不能使用get命令,此时无论开启关闭事务,管道中的其他命令也依然会正常执行
#pipe.get('hage')
#也可以用下面的语法将多个命令拼接到一起
# pipe.set('name', 'wyk').set('company', 'csdn').hset('hage', 'wyk',28).hincrby('hage','wyk',1)
#执行pipeline里的脚本
pipe.execute()
当管道中有命令报错时,无论管道是否开启事务都不会影响其他脚本的执行:
在管道中可以一次性获取多个命令的返回值,以列表形式:
pipe.get('name').get('company').hget('hage', 'wyk')
res = pipe.execute()
print(res)
对比Lua脚本
Redis的Script会当成一个命令,具有原子性,在执行Script的时候不会被其他的命令插入,因此更适合于处理事务;而管道虽然也会将多个命令一次性传输到服务端,但在服务端执行的时候仍然是多个命令,如在执行CMD1的时候,外部另一个客户端提交了CMD9,会先执行完CMD9再执行管道中的CMD2,因此事实上管道是不具有原子性的。
就场景上来说,正因为Lua脚本会被视为一个命令去执行,因为Redis是单线程执行命令的,所以我们不能在lua脚本里写过于复杂的逻辑,否则会造成阻塞,因此lua脚本适合于相对简单的事务场景。
而管道因为不具有原子性,因此管道不适合处理事务,但管道可以减少多个命令执行时的网络消耗,可以提高程序的响应速度,因此管道更适合于管道中的命令互相没有关系,不需要有事务的原子性,且需要提高程序响应速度的场景。
尾巴
管道可以提升我们程序中的响应时间,同时我们不能完全依赖于它的"事务"机制,只需要把管道当做"批处理"工具即可,在某些场合下,更需要结合管道和lua脚本一起使用。
文章不错?点个【在看】吧! ?