14. Redis watch监控
大约 2 分钟
redis 的 watch 监控
watch 监控,可以说说 乐观锁 和 悲观锁
乐观锁:
- 很乐观,认为什么时候都不会出问题,所以不会上锁,就更新数据的时候会去判断一下在此期间若数据发生了变化
- 乐观锁会先获取一个基础数据版本
- 更新数据的时候,会比较这个版本是否发生变化,若发生变化,则更新失败,若未发生变化,则更新数据
悲观锁:
- 很悲观,无论什么时候都认为会出问题,都要加锁
redis 的监控测试
用 watch 来加锁模拟银行取钱
- money 账户 有 2000
- outer 账户 有 500
- money 账户 给 outer 账户 500
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> set money 2000
OK
127.0.0.1:6379> set outer 500
OK
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 500
QUEUED
127.0.0.1:6379(TX)> INCRBY outer 500
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 1500
2) (integer) 1000
开始测试模拟多个线程来操作
redis 客户端 1
- money 账户 有 2000
- outer 账户 有 500
- money 账户 给 outer 账户 500 ,还未开始执行
127.0.0.1:6379> set money 2000
OK
127.0.0.1:6379> set outer 500
OK
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 500
QUEUED
127.0.0.1:6379(TX)> INCRBY outer 500
QUEUED
客户端 1 的事务操作还未开始执行,客户端 2 就进行了如下操作
127.0.0.1:6379> set money 10000
OK
127.0.0.1:6379> set money 10000
OK
此时执行客户端 1 的 exec 指令
127.0.0.1:6379(TX)> exec
(nil)
127.0.0.1:6379> get money
"10000"
发现客户端 1 执行 exec 的时候,是一个 nil ,说明变更失败,是因为 watch 监控到 money 有变动,因此事务执行失败
unwatch
发现事务执行失败了,需要使用命令 unwatch 解除监控
127.0.0.1:6379> UNWATCH
OK
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 1000
QUEUED
127.0.0.1:6379(TX)> INCRBY outer 1000
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 9000
2) (integer) 1500
这就是 redis 实现乐观锁的操作,一般使用场景会放到秒杀系统里面进行应用