9.redis锁
1.悲观锁:认为什么时候都会出问题,做什么操作都会加锁
2.乐观锁:很乐观,认为什么时候都不会出问题,更新数据时去判断一下,再此期间是否有人更改了这个数据!
MULTI(开启事务)/DISCARD(放弃事务)
使用watch 监视
使用案例1:模拟100块钱花去20块钱
127.0.0.1:6379> set money 100(设置总钱数:100)
OK
127.0.0.1:6379> set out 0(设置花去的钱:0)
OK
127.0.0.1:6379> WATCH money(监视money:拿到money的值)
OK
127.0.0.1:6379> MULTI(开启事务)
OK
127.0.0.1:6379> DECRBY money 20(总钱数花去20)-->执行前,会比较最新的money值和watch拿到的是否一致!不一致意味着其他线程对其做了更改,就会执行失败
QUEUED
127.0.0.1:6379> INCRBY out 20(花去的钱增加20)
QUEUED
127.0.0.1:6379> exec(执行事务)
1) (integer) 80(返回剩余的钱)
2) (integer) 20(返回花去的钱)
127.0.0.1:6379> get out(获取花去的钱数:20)
"20"
127.0.0.1:6379> get money(获取剩余的钱数:80)
"80"
乐观锁导致的事务执行失败:
两个线程:(起了两个redis客户端,同时对money做操作)
线程1:做money的-2操作和out的+2操作
线程2:在线程1的事务还没有exec时,更改money值为100
线程1:
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECRBY money 2
QUEUED
127.0.0.1:6379> INCRBY out 2
QUEUED
注意:这时线程1还没有执行exec
线程2:
127.0.0.1:6379> set money 1000(将money置为1000)
OK
这时;
线程1:最后执行事务,返回nil,发现事务执行失败
127.0.0.1:6379> EXEC
(nil)
127.0.0.1:6379> get money(发现money置为1000)
"1000"
解决方案:
127.0.0.1:6379> UNWATCH(先解锁)
OK
127.0.0.1:6379> WATCH money(重新获取锁,得到money的最新值,在进行上述的+-操作)
OK