Redis系列6 - Redis事务

Redis事务的概念:

 

  Redis 事务的本质是一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。

  总结说:redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。  

事务的特性

  • 事务过程中的命令按顺序依次执行,执行过程不受其他客户端发出的命令影响,事务中的一组命令是一个与外界隔离的操作单元。

  • 命令要么全部执行,要么全不执行。事务中命令的执行由EXEC命令触发。

Redis事务没有隔离级别的概念:

  批量操作在发送 EXEC 命令前被放入队列缓存,并不会被实际执行,也就不存在事务内的查询要看到事务里的更新,事务外查询不能看到。

Redis不保证原子性:

  Redis中,单条命令是原子性执行的,但事务不保证原子性,且没有回滚。事务中任意命令执行失败,其余的命令仍会被执行。

Redis事务的三个阶段:

  • 开始事务

  • 命令入队

  • 执行事务

Redis事务相关命令:

Redis使用MULTI, EXEC, DISCARD 和 WATCH 命令来实现事务功能。事务可以一次执行多个命令,并带有两个重要的保证: 

  • 事务中的所有命令都被序列化并按顺序执行。Redis执行事务期间,不会被其它客户端发送的命令打断,事务中的所有命令都作为一个隔离操作顺序执行。

  • Redis事务是原子操作,或者执行所有命令或者都不执行。EXEC 命令触发一个事务中所有命令的执行,所以,如果一个客户端断在调用EXEC 命令前丢失连接,那么所有的命令不会被执行,相反,如果EXEC 被调用,那么所有命令会被执行。当使用 append-only file 方式持久化时,Redis使用单个 write(2) 系统调用将事务写到磁盘上。但是,如果Redis服务器崩溃或被系统管理员以某种硬方式杀死,则可能只注册了部分操作。Redis重启的时候会检测到这种情况,并返回错误退出。使用 redis-check-aof 工具可以删除部分事务,这样Redis可以重新启动。

  watch key1 key2 ... : 监视一或多个key,如果在事务执行之前,被监视的key被其他命令改动,则事务被打断 ( 类似乐观锁 )

  multi : 标记一个事务块的开始( queued )

  exec : 执行所有事务块的命令 ( 一旦执行exec后,之前加的监控锁都会被取消掉 ) 

  discard : 取消事务,放弃事务块中的所有命令

  unwatch : 取消watch对所有key的监控

Redis事务使用案例:

这些命令的使用方式如下:

 

Copy

# 开启事务
MULTI
command1
command2
# 触发事务
EXEC

MULTI 命令用于开启一个事务,它总是返回 OK 。MULTI执行之后, 客户端可以继续向服务器发送任意多条命令, 这些命令不会立即被执行, 而是被放到一个队列中。

EXEC命令负责触发并执行事务中的所有命令,EXEC命令的回复是一个数组, 数组中的每个元素都是执行事务中的命令所产生的回复。其中, 回复元素的先后顺序和命令发送的先后顺序一致。

当使用 AOF 方式做持久化的时候, Redis 会令将事务写入到磁盘中。然而,如果 Redis 服务器因为某些原因被管理员杀死,或者遇上某种硬件故障,那么可能只有部分事务命令会被成功写入到磁盘中。Redis 在重新启动时发现 AOF 文件出了这样的问题,那么它会退出,并汇报一个错误。使用 redis-check-aof 程序可以修复这一问题:它会移除 AOF 文件中不完整事务的信息,确保服务器可以顺利启动。


 

(1)正常执行

 

(2)放弃事务

(3)若在事务队列中存在命令性错误(类似于java编译性错误),则执行EXEC命令时,所有命令都不会执行

(4)若在事务队列中存在语法性错误(类似于java的1/0的运行时异常),则执行EXEC命令时,其他正确命令会被执行,错误命令抛出异常。

 

(5)使用watch

      WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为。

被 WATCH 的键会被监视,并会发觉这些键是否被改动过了。如果有至少一个被监视的键在 EXEC 执行之前被修改了, 那么整个事务都会被取消, EXEC 返回空来表示事务已经失败。

当发生被监控的键被改变时,程序需要做的就是不断重试这个操作, 直到没有发生碰撞为止。

 

案例一:使用watch检测balance,事务期间balance数据未变动,事务执行成功

案例二:使用watch检测balance,在开启事务后(标注1处),在新窗口执行标注2中的操作,更改balance的值,模拟其他客户端在事务执行期间更改watch监控的数据,然后再执行标注1后命令,执行EXEC后,事务未成功执行。

一但执行 EXEC 开启事务的执行后,无论事务使用执行成功, WARCH 对变量的监控都将被取消。

故当事务执行失败后,需重新执行WATCH命令对变量进行监控,并开启新的事务进行操作。

 总结:

  

      通过上面的例子,可以看出Redis在执行事务命令的时候,在命令入队的时候, Redis 就会检测事务的命令是否正确,如果不正确则会产生错误。无论之前和之后的命令都会被事务所回滚,就变为什么都没有执行。

当命令格式正确,而因为操作数据结构引起的错误 ,则该命令执行出现错误,而其之前和之后的命令都会被正常执行。这点和数据库很不一样,这是需注意的地方。

对于一些重要的操作,我们必须通过程序去检测数据的正确性,以保证 Redis 事务的正确执行,避免出现数据不一致的情况。Redis 之所以保持这样简易的事务,完全是为了保证移动互联网的核心问题一----性能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java知路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值