数据库 \ redis \ Redis学习——Redis事务

Redis学习——Redis事务

总点击130
简介:Redis和传统的关系型数据库一样,因为具有持久化的功能,所以也有事务的功能!


Redis和传统的关系型数据库一样,因为具有持久化的功能,所以也有事务的功能!

有关事务相关的概念和介绍,这里就不做介绍。

在学习Redis的事务之前,首先抛出一个面试的问题。

面试官:请问Redis支持事务吗?如果支持和传统的关系型数据的事务有什么区别?

应试者:支持,但是是部分支持。Redis的事务和传统的关系型数据库事务有点不一样,传统的数据库事务一组操作单元,要么全部成功,要么全都失败。而Redis在执行一个命令集合的时候,可能会出现集合的一些命令成功,一些命令失败。

Redis 事务-中文官网:Redis 事务管理

Redis 事务| 菜鸟教程 :Redis 事务

Redis事务的学习笔记总结:


1:是什么?

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

2:能做什么?

一个队列中,一次性、顺序性、排他性的执行一系列命令

3:常用命令


Redis 事务命令

1   DISCARD

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

2   EXEC

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

3   MULTI

标记一个事务块的开始。

4   UNWATCH

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

5   WATCH key [key ...]

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

4:怎么玩?

案例1:正常执行

127.0.0.1:6379> KEYS *

(empty list or set)

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> set k3 v3

QUEUED

127.0.0.1:6379> EXEC #执行,全部执行成功

1) OK

2) OK

3) OK

127.0.0.1:6379> MGET k1 k2 k3  #查看执行结果

1) "v1"

2) "v2"

3) "v3"

127.0.0.1:6379>

案例2:放弃事务

127.0.0.1:6379> MULTI #开始事务

OK

127.0.0.1:6379> set k4 v4

QUEUED

127.0.0.1:6379> set k5 v5

QUEUED

127.0.0.1:6379> set k1 v11  #这里发现出错了,第一次设置k1 了

QUEUED

127.0.0.1:6379> DISCARD #放弃事务

OK

127.0.0.1:6379> MGET k1 k2 k3 k4 k5      #k4 k5 的值没有设置成功

1) "v1"

2) "v2"

3) "v3"

4) (nil)

5) (nil)

127.0.0.1:6379>

案例3:全体连坐(一个出错,全部执行失败)

127.0.0.1:6379> KEYS *  #查看当前的keys

1) "k1"

2) "k3"

3) "k2"

127.0.0.1:6379> MULTI  #开始事务

OK

127.0.0.1:6379> set k4 v4

QUEUED

127.0.0.1:6379> set k5 v5

QUEUED

127.0.0.1:6379> getandset k1  #这里有个操作出错 ,下面报错,

(error) ERR unknown command 'getandset'

127.0.0.1:6379> set k6 v6  # 这个命令依旧执行成功,放到Queued队列

QUEUED

127.0.0.1:6379> EXEC  #执行,出错

(error) EXECABORT Transaction discarded because of previous errors.

127.0.0.1:6379> MGET k1 k2 k3 k4 k5 k6    #k4 k5 k6 的值都没有设置成功,操作全部失败

1) "v1"

2) "v2"

3) "v3"

4) (nil)

5) (nil)

6) (nil)

127.0.0.1:6379>

案例4:冤头债主(一个出错,出错的不执行,其他的执行成功!)

127.0.0.1:6379> set k1 1  #将k1 修改为 1

OK

127.0.0.1:6379> keys *

1) "k1"

2) "k3"

3) "k2"

127.0.0.1:6379> MULTI  #开启事务

OK

127.0.0.1:6379> set k4 v4

QUEUED

127.0.0.1:6379> set v5 v5

QUEUED

127.0.0.1:6379> INCR k1  #k1 加1

QUEUED

127.0.0.1:6379> INCR k2 #k2 加1 ,因为k2的值为v2,这里最后执行会报错

QUEUED

127.0.0.1:6379> INCR k3 #k3 加1

QUEUED

127.0.0.1:6379> set k6 v6

QUEUED

127.0.0.1:6379> EXEC   #执行,除了 k2 k3 执行失败,其他的都执行成功。

1) OK

2) OK

3) (integer) 2

4) (error) ERR value is not an integer or out of range    #INCR k2 执行出错

5) (error) ERR value is not an integer or out of range      #INCR k3 执行出错

6) OK

127.0.0.1:6379> MGET k1 k2 k3 k4 v5 k6  #看到k4 v5 k6 设置成功

1) "2"

2) "v2"

3) "v3"

4) "v4"

5) "v5"

6) "v6"

127.0.0.1:6379>

案例5:watch监控(watch可以监控多个key,使用watch进行key的监控,相当于给key上锁,如果在事务中,监控的key的value发生变化,则整个事务的全部命令都执行失败)

127.0.0.1:6379> KEYS *

1) "k3"

2) "k4"

3) "k2"

4) "v5"

5) "k1"

6) "k6"

127.0.0.1:6379> MGET k1 k2 k3 k4 v5 k6

1) "2"

2) "v2"

3) "v3"

4) "v4"

5) "v5"

6) "v6"

127.0.0.1:6379> WATCH k1  #监控k1 第一步

OK

127.0.0.1:6379> MULTI  #开始事务 第二步

OK

127.0.0.1:6379> set k7 v7    #第三步

QUEUED

127.0.0.1:6379> set k2 v2222  #第四步

QUEUED

127.0.0.1:6379> set k3 v3333  #第五步

QUEUED

127.0.0.1:6379> set k8 v8  #第六步

QUEUED

127.0.0.1:6379> EXEC  #第七步  #执行结果为nil,说明执行失败

(nil)

127.0.0.1:6379> MGET k1 k2 k3 k4 v5 k6 k7 k8

1) "110"   #k1 的值被改了 ,其他的事务中的值都没有成功

2) "v2"

3) "v3"

4) "v4"

5) "v5"

6) "v6"

7) (nil)

8) (nil)

127.0.0.1:6379>

--

在执行第三 —— 第六步之间,使用另一个客户端修改k1 的值为 成110

另一个客服端执行:

127.0.0.1:6379> set k1 110

OK

案例5解释:因为另一个客服端修改 了k1的值,但是k1的值是被监控的,事务在执行的时候发现k1的值被修改了,则事务中的其他操作命令也不执行,即执行失败。

5:执行阶段

开启:以MULTI开始一个事务

入队:将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面

执行/撤销:由EXEC/Discard 命令触发/撤销事务

6:总结

单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断

没有隔离级别的概念:队列中的命令没有提交之前都不会实际的被执行,因为事务提交前任何指令都不会被实际执行,也就不存在”事务内的查询要看到事务里的更新,在事务外查询不能看到”这个让人万分头痛的问题

不保证原子性:redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚

意见反馈 常见问题 官方微信 返回顶部