redis事务开启,执行,监视变量以及错误处理

    redis中可以单独执行一个命令,也可以执行多条命令,为了保证原子性,redis中可以将多条命令放入到一个事务中,一般事务分为三个阶段,第一个呢,开启事务,命令入队和执行事务,接下来我们用一个转账的实例来讲解redis的事务,首先我们准备两个key,分别代表账户A和账户B,账户A向账户B转账50元,转账大家都知道必须是原子操作的,要么都成功,要么都失败,不可能出现A账户减了50元,账户B没有增加50元,这样的结果转账的人,肯定是不愿意看到的,下边我们就具体操作下。

这里我们用到几个命令

  • mulit 开启事务
  • exec 执行事务

127.0.0.1:6379> set account:a 100
OK
127.0.0.1:6379> set account:b 100
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> get account:a
QUEUED
127.0.0.1:6379> get account:b
QUEUED
127.0.0.1:6379> decrby account:a 50
QUEUED
127.0.0.1:6379> incrby account:b 50
QUEUED
127.0.0.1:6379> exec
1) "100"
2) "100"
3) (integer) 50
4) (integer) 150

    从结果大家看到,事务执行成功,账户A减了50元钱,账户B增加了50元,QUEUED是当执行该段事务时,其他命令是不允许对account:a和account:b操作的,这样就保证了事务的原子性。

 

    这是会有小伙伴问了,如果账户A给账户B转账的时候,账户A正好到了当月还信用卡银行的扣款日,扣掉了这100元钱,在向账户B转账的时候,账户A而转账失败,账户B却成功了,这样的系统我肯定是不敢用,不一定哪天钱就少了,也不符合事务的原子性,那么我们看看怎样解决这样的问题呢,我们动手操作一下,这里介绍一个命令,watch

  • watch 监视某个key的值,当值变化了,我们就取消事务

终端1确认账户A和账户B分别是100元,开启监视账户A

127.0.0.1:6379> get account:a
"100"
127.0.0.1:6379> get account:b
"100"
127.0.0.1:6379> watch account:a
OK

新开一个终端2,修改账户A的值,扣掉100元

127.0.0.1:6379> decrby account:a 100
(integer) 0
127.0.0.1:6379> get account:a
"0"

继续操作终端1,开启事务,账户A减去50,账户B增加50,然后提交事务

127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby account:a 50
QUEUED
127.0.0.1:6379> incrby account:b 50
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get account:a
"0"
127.0.0.1:6379> get account:b
"100"

    从执行结果来看,返回nil,而且账户B没有变化,这才是我们想要的结果。

 

    这里,当我们开启事务后,想取消事务又怎样做呢,使用discard命令,还是用转账的例子,我们来讲解下,这里,当我们买一个东西后,需要付款时,金额已经输入了,想想这个商品不是很满意时,我们怎样来操作呢

127.0.0.1:6379> set account:a 100
OK
127.0.0.1:6379> set account:b 100
OK
127.0.0.1:6379>
127.0.0.1:6379> multi
OK
127.0.0.1:6379> get account:a
QUEUED
127.0.0.1:6379> get account:b
QUEUED
127.0.0.1:6379> decrby account:a 50
QUEUED
127.0.0.1:6379>
127.0.0.1:6379> incrby account:b 50
QUEUED
127.0.0.1:6379>
127.0.0.1:6379> discard
OK
127.0.0.1:6379>
127.0.0.1:6379> get account:a
"100"
127.0.0.1:6379> get account:b
"100"

    从执行过程来看,账户A已经减了50元,而账户B增加了50元,使用discard命令后,我们在来查看账户A和账户B的余额,一点没有变化,说明事物取消成功。

 

    下边来聊聊redis事务错误处理,它有两个方面,第一,当我们开启事务时(multi),执行命令1,命令2,命令3,命令3呢出现数据类型转换错误,比如命令3是将一个字符串做自增处理时,肯定是不成功的,当我们提交事务时(exec),命令1和命令2会被执行成功,而命令3呢,会执行失败,这和我们的关系型数据库不同之处,再一点呢,就是,开启事务后,执行命令1,命令2,命令3,命令3是一个语法错误,不存在的命令执行时,这时,事务会自动退出,当然命令1,命令2都会失败,下面我们继续操作下。

  • 事务错误处理情况1

127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set aa iosoft2020
QUEUED
127.0.0.1:6379> set bb iosoft2021
QUEUED
127.0.0.1:6379> incrby aa 10
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) (error) ERR value is not an integer or out of range
127.0.0.1:6379> keys *
1) "bb"
2) "aa"

    从结果可以到,set aa和set bb执行成功。

 

  • 事务错误处理情况2

127.0.0.1:6379> keys *
1) "bb"
2) "aa"
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set cc iosfot2022
QUEUED
127.0.0.1:6379> set dd iosfot2023
QUEUED
127.0.0.1:6379>
127.0.0.1:6379> aaaaaaa
(error) ERR unknown command `aaaaaaa`, with args beginning with:
127.0.0.1:6379>
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379>
127.0.0.1:6379> keys *
1) "bb"
2) "aa"

    从结果可以看到,当执行aaaaaaa这个不存在的命令时,事务本身就结束了,当你在提交事务(exec)时,会报出事务被丢弃的错误,同样key cc和dd没有添加成功。

 

    这里很多公司使用redis事务来实现秒杀,怎样使用redis做秒杀呢,我会重新开启一篇文章。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值