这是我参与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中乐观锁的实现,
我是灰小猿,我们下期见!