redis实现乐观锁
redis实现乐观锁
悲观锁(Pessimistic Lock):顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁;传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁
乐观锁(Optimistic Lock):顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制;乐观锁适用于多读的应用类型,这样可以提高吞吐量,Redis就是利用这种check-and-set机制实现事务的
watch
在执行multi之前,先执行watch key1 key2......,可以监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断
unwatch
取消 watch 命令对所有 key 的监视;如果在执行 watch命令之后,exec 命令或 discard 命令先被执行了的话,那么就不需要再执行unwatch了
redis通过watch实现监控,相当于一把锁,可以实现乐观锁操作
# money=100
127.0.0.1:6379> set money 100
OK
# out=0:消费0元
127.0.0.1:6379> set out 0
OK
# 监控money
127.0.0.1:6379> watch money
OK
# 开启事务
127.0.0.1:6379> multi
OK
# money减少20,money=80
127.0.0.1:6379(TX)> DECRBY money 20
QUEUED
# 消费20,out=20
127.0.0.1:6379(TX)> INCRBY out 20
QUEUED
# 执行事务,没有异常
127.0.0.1:6379(TX)> exec
1) (integer) 80
2) (integer) 20
127.0.0.1:6379>
接着上面的money继续操作
# 监控money
127.0.0.1:6379> watch money
OK
# 开启事务
127.0.0.1:6379> multi
OK
# money减少10,money=70
127.0.0.1:6379(TX)> DECRBY money 10
QUEUED
# 消费10,out=30
127.0.0.1:6379(TX)> INCRBY out 10
QUEUED
# 在执行事务之前,新开一个窗口,更改money(如下),结果执行事务失败
127.0.0.1:6379(TX)> exec
(nil)
127.0.0.1:6379>
执行上面事务之前,新开一个窗口,更改money
127.0.0.1:6379> get money
"80"
127.0.0.1:6379> set money 1000
OK
如果事务执行失败,就先解除监控:unwatch,获取最新值后,再次监控
记得快乐