七天玩转Redis|Day4,Redis事务操作

1.正常执行事务

  • 第一步,开启事物:Multi
  • 第二部,命令入队

开启事务时候就需要向该事务中加入命令,将命令入队,这一步你可以任意写入你想要执行的命令。注意:在将命令添加到队列之后,命令并不会立即执行,而是返回一个QUEUED,表示入队成功!

  • 第三步,提交命令:Exec

在我们将所有的命令都入队之后,就可以提交执行这个事务了,提交事务的命令是:Exec

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> SET k3 v3
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) OK
3) "v1"
4) OK

2.取消事物执行

如果在我们的事务没有提交之前,你想要取消执行这个事务,那么可以使用Discard命令,这样这个事务就会被自动取消,其中入队的命令也不会被执行,在下一次执行事务时还需要重新再开启事务!

  • 取消事务:Discard
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> DISCARD
OK

3.事务编译时异常

在事务执行或者命令入队的时候也是会发生错误的,和在Java代码中一样,如果我们的命令在书写上就存在明显代码错误,那么就会发生编译时异常,这个时候会有错误提示,**但是事务仍能提交,但是提交之后,整个事务队列中的命令都不会执行,**比如下面的例子,我们随便写入一个不存在的命令并提交执行,执行完之后去查看我们的数据是否添加成功!

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET k5 v5
QUEUED
127.0.0.1:6379> SETGET k6 v6    #输入错误命令
(error) ERR unknown command `SETGET`, with args beginning with: `K6`, `V6`,
127.0.0.1:6379> GET k5
QUEUED
127.0.0.1:6379> EXEC    #事务执行报错
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> GET k6
(nil)

4.运行时异常

在Redis中如果事务中的命令存在运行时异常,那么在提交事务之后,不存在异常的命令同样会被执行,异常的命令会单独执行失败!


如下,我们在事务中输入一个运行时会发生错误的命令INCR k9,给k9加一,但是k9并不存在,所以在提交事务之后该命令会执行失败,但是其他没有异常的命令可以执行成功!

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET k7 v7
QUEUED
127.0.0.1:6379> INCR k9    #该命令运行时会报错,因为不存在k9
QUEUED
127.0.0.1:6379> GET k7
QUEUED
127.0.0.1:6379> SET k8 v8
QUEUED
127.0.0.1:6379> EXEC    #事务可以正常提交,但是异常的命令单独报错
1) OK
2) (error) ERR value is not an integer or out of range
3) "v7"
4) OK
127.0.0.1:6379> GET k8    #可以正常获取到k8的值
"v8"

5.Redis乐观锁实现

Redis中有锁的机制,且锁可以分为乐观锁和悲观锁

  • **悲观锁:**认为什么时候都可能出错,所以在任何时候都会加锁
  • **乐观锁:**认为什么时候都不会出错,所以什么时候都不会加锁,在更新数据的时候只需要去判断,在此期间是否有人修改过这个数据即可!

实现乐观锁,需要使用一个命令去监控我们要操作的字段,命令是:Watch key

127.0.0.1:6379> SET money 100    #设置money为100
OK    
127.0.0.1:6379> SET outMoney 0    #设置outMoney为100
OK
127.0.0.1:6379> WATCH money        #监控money
OK
127.0.0.1:6379> MULTI    #开启事务
OK
127.0.0.1:6379> DECRBY money 10    #money减10
QUEUED
127.0.0.1:6379> INCRBY outMoney 10    #outMoney加10
QUEUED
127.0.0.1:6379> EXEC    #提交事务,执行成功
1) (integer) 90
2) (integer) 10

上面是一个正确的操作,没有问题,

但是如果我们现在重复刚才的操作(正常情况下money应该变成80),但是并不急着提交事务,而且开启一个新的Redis客户端,在其中对我们的money加10,之后再提交上一个上一个事务,就会提示我们的money已经被修改,这个时候事务一定是执行失败的!

1、首先去监控money,并开始一个事务,将命令入队,但是不去提交,

127.0.0.1:6379> WATCH money
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECRBY money 10
QUEUED
127.0.0.1:6379> INCRBY outMoney 10
QUEUED

2、打开一个新的Redis客户端,修改money的值

127.0.0.1:6379> INCRBY money 10
(integer) 100

3、返回第一个Redis客户端,提交修改,并查询money的值,显示money值为100

127.0.0.1:6379> WATCH money
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECRBY money 10
QUEUED
127.0.0.1:6379> INCRBY outMoney 10
QUEUED
127.0.0.1:6379> EXEC
(nil)
127.0.0.1:6379> GET money
"100"

这就说明,在给字段添加监控的情况下通过事务去操作字段,如果在未提交时,有新的命令修改了字段值,那么事务一定会提交失败,但是在未监控的情况下,事务仍能提交成功!这就是Redis的乐观锁实现!

所以在实现乐观锁时,开启事务之前,一定要先给字段增加监控!

所以:Redis是可以实现乐观锁的!(面试的时候可是经常会问的!)

另外注意:Redis在每次事务提交之后,无论事务执行成功与否,该事务都会关闭,监控也会自动取消,在下次执行事务时都需要重新开启!

Conclude:

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值