Redis学习笔记---Redis事务

前言

Redis事务可以一次执行多个命令(按顺序地串行执行,执行中不会被其他命令插入,不许加塞)

1.简介

Redis事务可以一次执行多个命令(允许在一次单独的步骤中执行一组命令)。
特征:
[1]批量操作在发送EXEC命令前被放入队列缓存
[2]收到EXEC命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行
[3]在事务执行过程中,其他客户端提交的命令请求不会被插入到事务执行命令序列中
因此Redis事务有如下保证:
[1]Redis会将一个事务中的所有命令序列化,然后顺序执行
[2]执行中不会被其他命令插入,不许出现加塞行为

2.事务的处理的阶段与错误处理机制

[1] 三个阶段:
开始事务
命令入队
执行事务
[2]错误处理机制:
队列中的某个命令出现报告错误(即不存在的命令),执行时整个的所有队列都会被取消。

3.相关命令

DISCARD      # 取消事务,放弃执行事务块内的所有命令
EXEC         # 执行所有事务块内的命令
MULTI        # 标记一个事务的开始
UNWATCH      # 取消WATCH命令对所有key的监视
WATCH        # 监视一个(或多个)key,如果在事务执行之前这个(或这些)key被其他命令所改动,那么事务将被打断

4.相关示例

[1] Multi 和 Exec

需求: 转账功能, A向B账号转账50元
这是一个事务的例子,它先以Multi 开启一个事务,然后多个命令入队到事务中,最后由Exec命令触发事务

代码示例:
127.0.0.1:6379[1]> set account:a 80
OK
127.0.0.1:6379[1]> set account:b 10
OK
127.0.0.1:6379[1]> multi
OK
127.0.0.1:6379[1]> get account:a
QUEUED
127.0.0.1:6379[1]> get account:b
QUEUED
127.0.0.1:6379[1]> decrby account:a 50
QUEUED
127.0.0.1:6379[1]> incrby account:b 50
QUEUED
127.0.0.1:6379[1]> exec
1) "80"
2) "10"
3) (integer) 30
4) (integer) 60
127.0.0.1:6379[1]> get account:a
"30"
127.0.0.1:6379[1]> get account:b
"60"

解析说明:
1] 输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行
2] 直到输入Exec后,Redis会将之前队列中的命令依次执行。

[2] Discard 放弃队列运行

在这里插入图片描述

127.0.0.1:6379[1]> set count:a 80
OK
127.0.0.1:6379[1]> set count:b 10
OK
127.0.0.1:6379[1]> multi
OK
127.0.0.1:6379[1]> get count:a
QUEUED
127.0.0.1:6379[1]> get count:b
QUEUED
127.0.0.1:6379[1]> decrby count:a 50
QUEUED
127.0.0.1:6379[1]> incrby count:b 50
QUEUED
127.0.0.1:6379[1]> discard
OK
127.0.0.1:6379[1]> get count:a
"80"
127.0.0.1:6379[1]> get count:b
"10"

解析说明:
1] 输入Multi 命令开始,输入的命令都会依次进入命令队列中,但不会执行
2] 直到输入Exec 后, Redis会将之前的命令对列中的命令依次执行
3] 命令队列的过程中可以通过discard来放弃队列运行。

[3] 事务的错误处理
1) 事务的错误处理:

如果执行的某个命令报出了错误(非不存在的命令),则只有报错的命令不会被执行,而其他的命令都会执行,
不会回滚。
在这里插入图片描述

代码示例:
127.0.0.1:6379[1]> multi
OK
127.0.0.1:6379[1]> set hello hello
QUEUED
127.0.0.1:6379[1]> incr hello            #错误的命令
QUEUED
127.0.0.1:6379[1]> get hello
QUEUED
127.0.0.1:6379[1]> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) "hello"
2) 事务的错误处理:

队列中的某个命令出现了报告错误不存在的命令),执行时整个的所有队列都会被取消

代码示例:
127.0.0.1:6379[1]> multi
OK
127.0.0.1:6379[1]> set a 111
QUEUED
127.0.0.1:6379[1]> abc     # 命令出现报告错误
(error) ERR unknown command 'abc'
127.0.0.1:6379[1]> get a
QUEUED
127.0.0.1:6379[1]> exec
(error) EXECABORT Transaction discarded because of previous errors.
[4] 事务的Watch

Watch key[key…]
监视一个(或多个)key,如果在事务执行之前这个(或这些)key被其他命令所改动,那么事务将被打断。
需求:某一账户在一事务内进行操作,在提交事务前,另一个进程对该账户进行操作
我们开启两个窗口(假设有两个用户张三和李四同时对count:b的值进行修改)
在这里插入图片描述

  1. 张三在进行操作前先对 count:b加了watch的操作
    在这里插入图片描述
  2. 与此同时,李四在张三执行完 watch count:b 时,也对count:b进行了修改
    在这里插入图片描述
  3. 张三在继续执行自己的事务
    在这里插入图片描述
    可以看到最终事务是被终止了,且count:b为李四修改后的值
[5] UNWATCH

Redis 中的Unwatch 命令用于取消WATCH命令对所有key的监视
如果在执行WATCH 命令之后, EXEC命令或DISCARD命令先执行的话,那就不需要执行UNWATCH了。

127.0.0.1:6379[1]> watch count:b
OK
127.0.0.1:6379[1]> unwatch 
OK
127.0.0.1:6379[1]> incrby count:b 10     #这时对数据进行修改也不会造成事务的执行失败
(integer) 50
127.0.0.1:6379[1]> multi
OK
127.0.0.1:6379[1]> incrby count:b 10
QUEUED
127.0.0.1:6379[1]> get count:b
QUEUED
127.0.0.1:6379[1]> exec
1) (integer) 60
2) "60"
5.应用场景

[1] 一组命令必须同时都执行,或者都不执行
[2] 我们想要保证一组命令在执行的过程之中不被其他命令插入
[3] 商品秒杀(活动)
[4] 转账活动

发布了46 篇原创文章 · 获赞 2 · 访问量 2859

猜你喜欢

转载自blog.csdn.net/TheWindOfSon/article/details/104339119