事务失败返回_Redis 高级特性(一):事务处理

22f71b9d55152000fafb1e5e6f1399ec.png

最近对Redis的高级特性做了一些整理,作为分享和记录。

事务:访问并可能更新数据库中各种数据项的一个程序执行单元,通常由高级编程语言书写的用户程序的执行所引起。事务是用形如begin transaction和end transaction的语句来界定的。

事务的特性:

  • 可以一次执行多个命令,是一个单独的隔离操作,事务中所有命令都会序列化并按序执行,事务在执行过程中不会被其他客户端发来的命令所打断。
  • 事务是一个原子操作,其中的命令要么不执行,要么都执行。

事务在redis中的用法:

  • 当client在连接中发出MULTI命令(总是返回OK)时,这个连接就进入事务的上下文(begin transaction & end transaction),接下来client输入的后续命令会存放到一个队列中而不会执行。
  • 通过调用DISCARD ,客户端可以清空事务队列并放弃执行事务。
  • 当客户端发出EXEC命令时,redis顺序执行队列中的所有命令,并返回一个数组,其中每个元素都是执行任务命令的返回,如下图所示。

Redis在进行事务处理时,只能保证client发起的事务中的命令可以连续的执行而且不会插入其他的client命令。

可能发生的问题:

  • 1. 事务在执行EXEC之前,入队命令可能会出错,比如,命令产生语法错误或者甚至是内存错误(服务器可能会使用maxmemory限制最大内存)
  • 2. 命令可能在EXEC调用之后失败,例如事务中的命令处理了错误类型的键,比如将列表命令用在字符串键上。

问题的解决:

在Redis2.6.5之前,客户端的做法是检查命令入队所得的返回值;如果命令入队返回QUEUE,则入队成功;否则入队失败。如果有命令入队失败,则停止并取消这个事务。(即:MULTI和EXEC之间输入命令过程中即报错退出)

在Redis2.6.5之后,服务器对命令入队失败的情况做记录并在客户端调用EXEC命令时拒绝执行并放弃事务(在输完命令,EXEC执行时放弃事务)

旧的做法只执行那些入队成功的命令,忽略入队失败的命令。新的做法的好处是在流水线中包含事务变得简单了。发送事务和读取事务的回复都只需要和服务器进行一次通讯。

在EXEC之后产生的错误并未特殊处理,即使某些命令执行错误,其他命令仍然会继续执行。

Redis不支持回滚

  • 原因:Redis命令只会因为语法错误或者将命令用在错误类型的键上(这些错误在入队时不能被发现)而失败,从实用性的角度讲,这些错误是编程错误,应该在开发过程被发现而不是生产环境中。
  • 好处:不需要做回滚支持,所以内部简单快速。

放弃事务:DISCARD

放弃事务时,事务队列被清空,客户端从事务状态退出。

给EXEC命令加上执行条件:WATCH

WATCH命令使得EXEC命令有条件执行;该条件指的是,事务只能在所有被监视的键没有修改的前提下执行,不满足条件的话,事务被取消。对键的监视从WATCH命令执行开始生效,直到调用EXEC为止。(监视带过期时间的key不在此列,key过期仍然会执行事务)

当EXEC被调用时,无论事务是否成功执行,对键的监视都会取消。

使用无参数的UNWATCH可以手动取消对所有键的监视。应用场景:对于一些需要改动多个键的事务,有时候程序需要同时对多个键加锁,检查这些键对应的是否符合程序要求。如果值达不到要求时,可以使用UNWATCH命令取消目前对键的监视,中途放弃事务。

使用WATCH命令可以实现乐观锁(check-and-set,CAS)。对资源的key使用WATCH命令,当EXEC执行之前,如果有其他客户端修改了key对应的值,则本EXEC的执行就会失败,会一直重复直到不发生碰撞为止。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值