Redis重制(十三)redis乐观锁(watch)

25 阅读2分钟

这里我们来学习watch监控命令,用watch来实现redis的乐观锁。

 

我们先来复习一下mysql中乐观锁和悲观锁的定义:

悲观锁:

很悲观,认为什么时候都会出问题,无论做什么都会加锁!

 

乐观锁:

1)      很乐观,认为什么时候都不会出问题,所以不会上锁!更新数据的时候去判断一下,在此期间是否有人修改过这个数据,

2)      获取version

3)      更新的时候比较version,version发生改变则提交失败

 

在MySQL中乐观锁是使用version来实现,在redis中,乐观锁使用watch来实现。

 

下面我们使用一个例子来模拟一下乐观锁的操作:

1:正常消费操作

127.0.0.1:6379> set money 100                # 设置money 100
OK
127.0.0.1:6379> set out 0                         # 设置 out 消费0
OK
127.0.0.1:6379> watch money                  # 开启监控
OK
127.0.0.1:6379> multi                               # 开启事务
OK
127.0.0.1:6379(TX)> INCrBY out 10           # 消费 + 10
QUEUED
127.0.0.1:6379(TX)> decrby money 10      # money -10
QUEUED
127.0.0.1:6379(TX)> exec                          # 执行事务,发现成功。
1) (integer) 10
2) (integer) 90
127.0.0.1:6379>                                        # 事务结束之后,watch自动失效

 

我们上边这是一个完整的乐观锁操作过程。但是在实际应用中,可能会出现并发,也就是说,在你事务执行过程中money就被其他人改变了,我们下边使用两个窗口来模拟一下并发操作。

 

2:并发消费操作

(1):窗口1:

127.0.0.1:6379> watch money                  # 监控money
OK
127.0.0.1:6379> multi                               # 开启事务
OK
127.0.0.1:6379(TX)> decrby money 10      # 消费10
QUEUED
127.0.0.1:6379(TX)> incrby money 10        # 消费金额新增10元
QUEUED
127.0.0.1:6379(TX)>                                   # 这里我们不执行事务,模拟并发进入窗口2

(2):窗口2:

127.0.0.1:6379> watch money                  # 监控money
OK
127.0.0.1:6379> multi                               # 开启事务
OK
127.0.0.1:6379(TX)> set money 200           # 改变money
QUEUED
127.0.0.1:6379(TX)> exec                          # 执行事务
1) OK
127.0.0.1:6379>                                        # 监控失效

 

(3):再次回到窗口1

执行事务我们会发现,执行失败

127.0.0.1:6379> watch money                  # 监控money
OK
127.0.0.1:6379> multi                               # 开启事务
OK
127.0.0.1:6379(TX)> decrby money 10      # 改变money
QUEUED
127.0.0.1:6379(TX)> incrby money 10        # 改变out
QUEUED
127.0.0.1:6379(TX)> exec                          # 执行事务失败,因为在执行事务之前,money已经被修改了。
(nil)
127.0.0.1:6379>                                        # 注意:此时watch监控还未失效

 

(4):重试:在窗口1中

正常在我们程序逻辑中,用watch监控的事务执行失败之后会再次执行。

注意,watch监控的事务实行失败之后,watch还未失效,想要获取新的watch监控,需要先解除watch

127.0.0.1:6379> unwatch                          # 先解除watch
OK
127.0.0.1:6379> watch money                  # 监控money
OK
127.0.0.1:6379> multi                               # 开启事务
OK
127.0.0.1:6379(TX)> get money                # 获取money
QUEUED
127.0.0.1:6379(TX)> decrby money 10      # 消费10
QUEUED
127.0.0.1:6379(TX)> incrby out 10      # 消费金额增加10
QUEUED
127.0.0.1:6379(TX)> exec                   # 执行事务
1) "200"
2) (integer) 190
3) (integer) 20
127.0.0.1:6379>

 

经典面试题:redis如何实现乐观锁?

使用watch

 

以上大概就是redis乐观锁的基本实现。

 

有好的建议,请在下方输入你的评论。