Redis实现乐观锁
# Redis实现乐观锁
监控: Watch
# 1. 悲观锁
- 很悲观,认为什么时候都会出问题,无论做什么都会加锁!
# 2. 乐观锁
很乐观,认为什么时候都不会出问题,所以不会上锁! 更新数据的时候去判断一下,在此期间是否有人修改过这个数据,
获取version
更新的时候比较 version
# 3. redis监视测试
# 3.1 正常执行
watch
: 监视
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money # 监视 money 对象
OK
127.0.0.1:6379> multi # 事务正常结束,数据期间没有发生变动,这个时候就正常执行成功!
OK
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> incrby out 20
QUEUED
127.0.0.1:6379> exec
1) (integer) 80
2) (integer) 20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 3.2 测试多线程修改值 , 使用watch 可以当做redis的乐观锁操作!
# 3.2.1 问题
- 线程1
127.0.0.1:6379> watch money # 监视 money 对象
OK
127.0.0.1:6379> multi # 开启线程
OK
127.0.0.1:6379> decrby money 10
QUEUED
127.0.0.1:6379> incrby out 10
QUEUED
127.0.0.1:6379> exec
(nil)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
- 线程2
127.0.0.1:6379> get money
"80"
127.0.0.1:6379> set money 1000 # 修改 money
OK
1
2
3
4
2
3
4
在线程1执行
exec
操作之前,我们先执行线程2,修改money的值后, 导致事务执行失败,结果: 执行exec
后 出现(nil)
# 3.2.2 解决
unwatch
: 如果发现事务执行失败,就可先解锁
127.0.0.1:6379> unwatch # 如果发现事务执行失败,就可先解锁
OK
127.0.0.1:6379> watch money # 获取最新的值,再次监视,select version(通过版本)
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 1
QUEUED
127.0.0.1:6379> incrby out 1
QUEUED
127.0.0.1:6379> exec # 比对监视的是否发生变化
1) (integer) 999
2) (integer) 21
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
如果修改失败,获取最新的值就好
# 4. 场景
秒杀
参考: https://www.cnblogs.com/jasonZh/p/9522772.html
上次更新: 2023/03/27, 08:56:25