Redis实战(四)事务

12

是什么?

可以一次执行多个命令,本质是一组命令的集合。一个事务中所有命令都会序列化,按顺序地串行化执行而不会被其他命令插入,不许加塞

Redis事务没有提供绝对的一致性,也就是没有ACID特性,也不支持事务回滚

能干嘛?

将指令放在一个队列中,用来一次性、顺序性、排他性的执行一系列命令。

Redis事务与数据库事务的区别

  1. 单独的隔离操作:Redis的事务仅仅是保证事务里的操作都会被连续独占的执行,Redis命令执行是单线程架构,在执行完事务内所有指令前是不能再去同时执行其他客户端的请求的
  2. 没有隔离级别的概念:因为事务提交前任何指令都不会被实际执行,也就不存在“事务内的查询要看到事务内的更新,在事务外查询不能看到”这种问题了
  3. 不保证原子性:Redis的事务不保证原子性,也就是不保证所有指令同时成功或同时失败,只有决定是否开始执行全部指令的能力,没有执行到一半进行回滚的能力
  4. 排他性:Redis会保证一个事务内的命令依次执行,而不会被其他命令插入

实操命令

基本命令

  • multi:开始事务命令,返回OK
  • exec:提交事务,开始执行
  • discard:丢弃事务
  • watch:

正常执行

multi
set k1 v1
set k2 v2
exec

放弃事务

multi
set k1 v1
set k2 v2
discard

全体连坐
当redis发现语法错误的时候,在提交前就会报错,提交的时候会提示检查到事务命令有错误,事务中所有命令都不会执行。

multi
set k1 v2
set k2 # 语法错误
exec

冤头债主
如果在提交事务时命令本身没有语法错误,但是命令执行时发生运行时错误,Redis还是会继续顺序执行下一个的命令,而不是回滚或停止执行。

set email sample@qq.com
multi
set k1 v2
incr email # 字符串不能递增,出错
set k2 v2
exec

Watch监控
Redis使用watch来提供乐观锁定,类似于CAS(check-and-set),在开始事务前,先watch需要在事务中修改的key,然后开启事务进行提交,当在此期间有其他用户修改了被watch的key,则事务执行失败,返回nil

set k1 v2
watch k1 # 监控k1
multi
set k2 v2 # 如果在事务执行前,k1被修改,那么该事务整体都不会被执行
set k1 v1
exec

手动取消监控

watch k1
unwatch k1

注意:一旦执行了exec,那么在这之前加的watch就会全部被取消,当客户端失去连接的时候,watch也都会被取消。

小总结

  • 开启:通过multi开启事务
  • 入队:将多个命令入队到事务中,这些命令不会被立即执行,而是放到等待执行的事务队列里面
  • 执行:以exec命令执行事务