Redis事务与Pipeline功能

一、Redis事务

Redis中的事务(transaction)是一组命令的集合,对事物的支持有限,不能保证原子性,在集群分片环境中,由于不同key可能存在不同的机器上,所以造成事务无法使用(可以简单使用,不推荐)

事务相关命令
  • multi命令,用于开启事务,标记一个事务块的开始,事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由 exec命令原子性(atomic)地执行
  • exec命令,执行事务的命令,返回结果是一个Array结构的数据,其中每个元素是事务中顺序执行的命令的结果
  • watch命令,监控一个或者多个key,如果这些key在提交事务(exec)之前被其他用户修改过,那么事务将执行失败,需要重新获取最新数据重头操作(类似于乐观锁)
  • discard命令,放弃当前事务,discard命令会清空事务命令队列,并退出事务(注意discard并不是rollback回滚)
  • unwatch命令,取消watch命令对所有key的监控,所有监控锁将会被取消
Redis事务特性
  • 单独的隔离操作:事务中的所有命令会被序列化、按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断
  • 没有隔离级别的概念:队列中的命令在事务没有被提交之前不会被实际执行
  • 不保证原子性:Redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行,不会回滚
user:0>multi
"OK"

user:0>set a 1
"QUEUED"

user:0>set b 2
"QUEUED"

user:0>discard
"OK"

user:0>exec
"ERR EXEC without MULTI"

user:0>get a
null

user:0>multi
"OK"

user:0>set a man
"QUEUED"

user:0>set b 2
"QUEUED"

user:0>set c 3
"QUEUED"

user:0>exec
 1)  "OK"
 2)  "OK"
 3)  "OK"
 
user:0>del a b c
"3"

user:0>multi
"OK"

user:0>set a man
"QUEUED"

user:0>incr a    //这里执行出错,但是这个事务不会回滚,其它命令执行成功
"QUEUED"

user:0>set b 8
"QUEUED"

user:0>set c 9
"QUEUED"

user:0>exec
 1)  "OK"
 2)  "ERR value is not an integer or out of range"
 3)  "OK"
 4)  "OK"
user:0>get b
"8"

user:0>get c
"9"

user:0>del a b c
"3"

user:0>multi
"OK"

user:0>set a 1
"QUEUED"

user:0>qwe //这里本身就是一个错误命令,Redis第一时间感知,整个事务不会执行成功
"ERR unknown command 'qwe'"

user:0>set b 2
"QUEUED"

user:0>exec
"EXECABORT Transaction discarded because of previous errors."

user:0>get a
null
Redis事务中两类错误:
  • 命令语法错误、参数错误等,事务提交前即可感知,然后discard当前事务
  • 命令进入事务的命令队列,但在执行exec后出错,执行成功的其它命令不会回滚,也就是说此时Redis会跳过这个错误命令

上述案例中已经详细演示并说明

二、Redis Pipeline(管道)功能

Redis pipeline功能允许客户端可以一次发送多条命令,而不等待上一条命令执行的结果,并在执行完后一次性将结果返回。pipeline对于qps的提升非常大

为什么pipeline功能可以提升性能?

每个请求命令发出后client通常会阻塞并等待redis服务器处理,redis处理完请求命令后会将结果通过响应报文返回给client,因此当执行多条命令的时候都需要等待上一条命令执行完毕才能执行

由于通信会有网络延迟,假如client和server之间的包传输需要0.125秒,执行3个命令6个报文至少需要0.75秒才能完成,然而Redis服务端每秒能执行100个命令,这显然没有充分利用 Redis的处理能力

pipeline通过减少客户端与redis的通信次数来实现降低往返延时时间,而且Pipeline 实现的原理是队列,而队列的原理是时先进先出,这样就保证数据的顺序性

注意:

  1. 用 pipeline方式打包命令发送,redis server必须将部分请求放到队列中(使用内存),执行完毕后一次性发送结果。打包的命令越多,缓存消耗内存也越多。所以并不是打包的命令越多越好。具体多少合适需要根据具体情况测试

  2. pipeline期间将“独占”链接,此期间将不能进行非“管道”类型的其他操作,直到pipeline关闭;如果你的pipeline的指令集很庞大,为了不干扰链接中的其他操作,你可以为pipeline操作新建Client链接,让pipeline和其他正常操作分离在2个client中。

适用场景

有些系统可能对可靠性要求很高,每次操作都需要立马知道这次操作是否成功,是否数据已经写进redis了,那这种场景就不适合

如果需要批量的将数据写入redis,允许一定比例的写入失败,那么这种场景就可以使用了,比如10000条一下进入redis,可能失败了2条没关系,后期有补偿机制就行了,比如短信群发这种场景,如果一下群发10000条,按照第一种模式去实现,那这个请求过来,要很久才能给客户端响应,这个延迟就太长了,如果客户端请求设置了超时时间5秒,那肯定就抛出异常了,而且本身群发短信要求实时性也没那么高,这时候用pipeline最好了。

三、Redis事务与pipeline功能区别

  • pipeline选择客户端缓冲,multi选择服务端缓冲
  • 请求次数的不一致,multi需要每个命令都发送一次给服务端,pipeline最后一次性发送给服务端,请求次数相对于multi减少
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值