Redis实现乐观锁

144 阅读2分钟

这是我参与2022首次更文挑战的第20天,活动详情查看:2022首次更文挑战

hello,你好呀,我是灰小猿,一个超会写bug的程序猿!

今天这一篇文章我们来讲解一下在Redis中如何实现乐观锁并监听数据。

Redis乐观锁实现

Redis中其实也是有锁的机制的,而且锁可以分为乐观锁和悲观锁,

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

所以如果想要实现乐观锁,我们需要使用一个命令去监控我们要操作的字段,在Redis中这个命令是:

WATCH key

  • key要监控的字段的索引

如果想要实现锁,那么一定是要伴随着事务进行的。

我们以超市消费作为一个例子来实现Redis的乐观锁和监控,先定义一个money字段表示我们的钱,定义一个outMoney字段表示花出去的钱,我们现在要开启一个事务执行下面这样一个任务:“money'花出去10元,则outMoney增加10元”,在开启事务之前先使用WATCH命令去监控money字段。

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在每次事务提交之后,无论事务执行成功与否,该事务都会关闭,监控也会自动取消,在下次执行事务时都需要重新开启!

以上就是Redis中乐观锁的实现,

我是灰小猿,我们下期见!