Redis进阶-事务

 

目录

                  ▪️ 基础命令介绍:

                  ▪️ 初步了解:

▪️ 事务 MULTI

▪️ 取消事务 DISCARD

▪️ 错误处理

▪️ 监控 WATCH

▪️ 取消监控 UNWATCH

 


 

     ▪️ 基础命令介绍:

             https://blog.csdn.net/qq_42816268/article/details/115178561

     ▪️ 初步了解:

              1、描述:将多个命令放入事务队列中,redis将按顺序逐个执行,要么都执行成功,若有一个失败则都不执行(有一种情况除外,请看小节"错误处理")。

              2、场景举例:银行转账,假若银行卡A转账给银行卡B,成功的情况是银行卡A的余额减少,银行卡B的余额增加,若其中一种情况没发生,则整个转账流程失败,两张银行卡的余额都不会改变。

              3、redis中事务的性质是顺序性的:redis会将加入到事务队列中的命令逐个按顺序执行。

              4、redis中事务是具有单独隔离:其他客户端的命令不会对当前客户端的事务造成影响(例如WATCH、DISCARD)。

              5、redis中事务在一定意义上是具有原子性的:要么全部执行,要么都不执行(为什么说是在一定意义上呢,请看本篇文章小节"错误处理")。

▪️ 事务 MULTI

              1)语法:MULTI  .....命令1.......命令2.........  EXEC

              2)语意:发送事务指令MULTI告诉redis服务器,接下来我会输入多个命令,以事务结束指令EXEC结束

              3)要点:这两个指令之间的命令要么都执行成功,若其中失败一个则都不执行(有一种情况就算出错了其他命令也会执行,请看事务的错误处理)

127.0.0.1:6379> MULTI           // 发送事务开始指令 MULTI ,返回值OK表示事务开始
OK
127.0.0.1:6379> SET name lyh    // 事务中的命令1:设置字符串类型key = name,value = lyh,命令不会马上执行,返回值QUEUED,而是进入队列进行排队
QUEUED
127.0.0.1:6379> SET age 19      // 事务中的命令2:设置字符串类型key = age,value = 19
QUEUED
127.0.0.1:6379> EXEC            // 发送事务结束指令 EXEC,返回值为所有进入事务队列的命令各自执行后的返回值组成的列表
1) OK
2) OK

127.0.0.1:6379> MULTI           // 再次发送开始指令 MULTI
OK
127.0.0.1:6379> INCR age        // 使字符串类型key = age的value增加1 (此时age = 19)
QUEUED 
127.0.0.1:6379> INCR name       // 使字符串类型key = name的value增加1 (此时name = lyh)
QUEUED
127.0.0.1:6379> EXEC            // 输入此次事务结束指令 EXEC,由于INCR name命令报错了,所以INCR age虽然执行成功了,但是进行了回退,value还是19
1) (integer) 19
2) (error) ERR value is not an integer or out of range

127.0.0.1:6379> GET age         //输出key = age的值后发现,受到事务的影响,值确实没有改变
"19"
127.0.0.1:6379> GET name        
"lyh"


              

▪️ 取消事务 DISCARD

              1)语法:DISCARD

              2)语意:取消事务,并且事务里的命令都不会执行

127.0.0.1:6379> GET name       //name = lyh
"lyh"
127.0.0.1:6379> MULTI          //开启事务
OK
127.0.0.1:6379> SET name cxg   //事务中命令1:设置name = cxg
QUEUED
127.0.0.1:6379> DISCARD        //取消事务
OK
127.0.0.1:6379> GET name       //事务中的命令未执行
"lyh"

 

▪️ 错误处理

              1)要点:若在输入事务内要执行的命令时,redis处理错误的方式:

                      1、若时语法错误,则事务直接结束,其他任何事务中的命令都不执行

                      2、若执行时出错,比如事务中的命令没有语法错误,但是在执行时发生了运行错误,比如某个值是字符类型,然后在它上+1,就会报类型错误,redis在事务中处理这种错误时,会把错误放进事务中所有命令的返回值组成的列表中,这条事务中的其他命令也会接着执行,并且都不会被该运行错误影响,redis 不支持回滚,所以严格意思上redis不具备原子性

127.0.0.1:6379> MULTI                //开启事务
OK
127.0.0.1:6379> SET name lyh         //设置name = lyh
QUEUED
127.0.0.1:6379> SET1 age 19          //执行错误命令SET1,直接报错,事务也就停止了
(error) ERR unknown command `SET1`, with args beginning with: `age`, `19`, 
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> GET name             //由于事务中出现语法错误,事务中所有的命令都不执行,所以设置的name = lyh也没生效
(nil)


127.0.0.1:6379> SET name lyh        //设置name = lyh
OK
127.0.0.1:6379> SET weight 150      //设置weight = 150
OK
127.0.0.1:6379> SET height 180      //设置height = 180
OK
127.0.0.1:6379> MULTI               //开启事务
OK
127.0.0.1:6379> INCR weight         //weight = 150 + 1
QUEUED
127.0.0.1:6379> INCR name           //name = lyh + 1   由于类型不是数值类型,会报错,属于运行错误
QUEUED
127.0.0.1:6379> INCR height         //height = 180 + 1
QUEUED
127.0.0.1:6379> EXEC                //事务结束,发现事务中没有报错的命令都执行成功了
1) (integer) 151
2) (error) ERR value is not an integer or out of range
3) (integer) 181
127.0.0.1:6379> GET weight          //确实weight的值加1了,所以说明在事务中,错误类型是运行错误的话redis是直接跳过的,不会影响其他事务中的命令
"151" 

         

▪️ 监控 WATCH

              1)语法:WATCH key

              2)语意:监控某一个key,若在事务执行过程中,该key的值被事务中命令以外的命令(包括其他客户端)修改时,则该事务不被执行

              3)要点:

                         1、主要就是看开启监控到事务结束指令EXEC执行之前,监控的key是否被其他客户端或者本客户端修改,若修改了则事务不执行

                         2、要模拟多个客户端也容易,开多个命令行窗口连接多个redis即可

                         3、单独隔离操作:只会设置当前客户端的监控,并不会影响其他客户端的

127.0.0.1:6379> GET age         //获取到 age = 19
"19"
127.0.0.1:6379> GET name        //获取到 name = cxg
"cxg"
127.0.0.1:6379> WATCH name      //监控name键,若事务执行之前name的值被修改,则该事务不被执行
OK
127.0.0.1:6379> SET name lyh    //修改被监控的键name = lyh
OK
127.0.0.1:6379> MULTI           //开启事务
OK
127.0.0.1:6379> GET age         //获取age的value
QUEUED
127.0.0.1:6379> EXEC            //如果事务执行成功,返回值应该为19,但由于事务结束指令EXEC之前被监控的键name的值被修改,所以事务不执行
(nil)

                  

▪️ 取消监控 UNWATCH

              1)语法:UNWATCH

              2)语意:取消监控所有的key

              3)要点:单独隔离操作:只会取消当前客户端的WATCH,并不会影响其他客户端的WATCH

127.0.0.1:6379> WATCH name       //监控name键
OK
127.0.0.1:6379> SET name lyh     //修改被监控的name键的value为lyh
OK
127.0.0.1:6379> UNWATCH          //取消所有被监控的key
OK
127.0.0.1:6379> MULTI            //开启事务
OK
127.0.0.1:6379> SET name cxg     //修改name = cxg
QUEUED
127.0.0.1:6379> GET name         //获取name
QUEUED
127.0.0.1:6379> EXEC             //事务结束,发现即使被监控的name键被修改事务仍然正常执行,因为之前用UNWATCH取消了所有key的监控
1) OK        
2) "cxg"

 

若有缺陷,欢迎指正,之后会把此系列文章相较于在其他地方看到的有缺陷的知识点继续进行补充

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值