redis事务的基本命令组合有:multi,exec,discard,watch;它们允许单步执行多个命令,并提供两个保证:

  • 事务中的所有命令被放到缓存队列中顺序执行,操作具有隔离性
  • 事务中的所有命令要么全部执行,要么都不执行,所以操作具有原子性,但是不保证每一个命令操作的正确性!

使用方法如:multi命令开启事务,exec命令执行所有的操作;multi和exec之间的操作命令会被缓存到一个队列中:

 

> MULTI
OK
> INCR foo
QUEUED
> INCR bar
QUEUED
> EXEC
1) (integer) 1
2) (integer) 1

 

上面是一个简单的事务操作,通过提示可以看出,redis是将命令都缓存到一个队列中进行执行的,但是命令执行正确与否确不保证,例如:

127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr foo
QUEUED
127.0.0.1:6379> set bar xxx dd
QUEUED
127.0.0.1:6379> exec
1) (integer) 3
2) (error) ERR syntax error
可以看出上面的事务执行过程中,incr foo操作正常执行,set bar xxx dd命令执行失败,所以redis事务没有回滚操作!为什么redis不支持事务呢?它有自己的解释:

  • redis命令在语法错误的情况下会执行失败,这时候事务就会执行失败,这种错误在开发过程中也很容易被发现
  • redis因为不支持回滚,所以内部事务的执行被简化了,因而执行速度也更快

总之,在可确定命令不出错的情况下,redis事务的执行效率是很高的

discard用于终止事务的执行:

> SET foo 1
OK
> MULTI
OK
> INCR foo
QUEUED
> DISCARD
OK
> GET foo
"1"

watch用于在事务中提供一个check-and-set(CAS)的作用,用于监控key值是否改变,watch可以监控多个key值,如果被监控的key值改变了或者被删除了,则事务执行失败:

 127.0.0.1:6379> set key 1

OK
127.0.0.1:6379> watch key  ### 监控key值
OK
127.0.0.1:6379> set key 2   ### 修改key值
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set key 3  ### key的监控值被修改了
QUEUED
127.0.0.1:6379> exec        ### 执行失败
(nil)
127.0.0.1:6379> get key   ###得到是2
"2"

上面是修改被监控的对象key的值后再执行事务

127.0.0.1:6379> set key 1
OK
127.0.0.1:6379> watch key
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set key 2
QUEUED
127.0.0.1:6379> exec
1) OK
127.0.0.1:6379> get key
"2"

上面是监控的值并没有改变,而是在事务中执行对该key赋值的操作,可见事务执行成功

同样,如果在事务执行之前,如果key值被删除了,事务执行也会失败。

posted on 2022-01-12 22:56  Judy518  阅读(63)  评论(0编辑  收藏  举报