Redis 的事务

摘要:redis 的事务,redis 是不完全支持事务的,redis 事务操作命令有 multi,discard,exec,watch,unwatch 等。

Redis 的事务

其实 redis 的事务理念和 mysql 都差不多,就是一条命令、或者一组命令要么同时成功,要么同时失败。但是 redis 一个事务中的所有命令都会被串行化,按顺序的串行化执行而不会被其它命令插入,不许加塞。

简单来解释就是一个队列中、一次性、顺序性、排他性的执行一系列命令。


Redis 事务的常用命令

MULTI 标记一个事务块的开始。 

EXEC 执行所有事务块内的命令。 

DISCARD 取消事务,放弃执行事务块内的所有命令。 

WATCH key [key ...] 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。 

UNWATCH 取消 WATCH 命令对所有 key 的监视。


Redis 的事务基本操作

正常执行事务流程。

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k1
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) OK
3) "v1"

放弃提交事务。

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 v11
QUEUED
127.0.0.1:6379> set k2 v22
QUEUED
127.0.0.1:6379> DISCARD
OK
127.0.0.1:6379> get k1
"v1"

不过 redis 没有事务隔离级别的概念,所有队列中的命令,没有提交之前都不会被实际的执行,因为事务没有被实际的执行,也就不存在,我自己在事务内的更新,我再次查看会查看到。


Redis 不完全支持事务

为什么说 redis 不完全支持事务呢?因为他并不像 mysql 那样,如果发生报错所有的 sql 都会回滚,但是 redis 并不会,如果 redis 在操作过程中发生了一个很明显的报错,redis 就不会 exec 成功。

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> dfsffd k1
(error) ERR unknown command `dfsffd`, with args beginning with: `k1`, 
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k1
(nil)

比如上面这组操作,我们输入一个不存在的命令 dfsffd k1 之后,redis 立刻察觉出来并抛出报错,虽然最后我们 exec 提交事务,但是 redis 会告诉我们事务提交失败,所有命令都不会成功。

但是我们如果在执行过程中,使用了错误的操作,redis 没有明显的给我提示报错,那么我们最后是可以 exec 提交事务成功的,只不过是提交时候 redis 才会抛出错误信息,那么没有抛出错误信息的会执行成功,抛出错误信息的会失败。

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 aa
QUEUED
127.0.0.1:6379> INCR k1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
127.0.0.1:6379> MGET k1 k2
1) "aa"
2) "v2"

比如上面这组命令在事务执行过程中,我们给一个 key 为 aa 的值,执行 incr 自增 1 的命令时,会返回 queued 提示,表面上看着是正常的,但其实 incr 根本无法给字符串 aa 自增 1,redis 也没有抛出错误。最后我们 exec 提交后,会发现正常的命令会执行成功,错误的使用命令就会报错。

根据以上的测试发现 redis 对事务的支持是部分支持的,并不能保证事务的原子性,也不是像 mysql 那样完全支持的。


WATCH 和 UNWATCH 命令

watch 相当于一个乐观锁,如果检测到你要提交的事务被其他事务改动过,就提交失败,只有你的事务提交中的 key 没有被其他事务改过,才会提交成功。

利用 watch 监控一个或者多个 key,假如你开启 watch 后,有任何的 key 发生了变化, exec 提交命令执行的所有的事务都将被放弃。避免你在操作过程中有其他会话客户端修改你要改的 key,保证两个会话修改同一个 key 的变动发生在一个同一个事物中。

我们也可以在利用 unwatch 命令来取消检测。

结束语:感谢您对本网站文章的浏览,欢迎您的分享和转载,但转载请说明文章出处。
Top