1. 悲观锁
- 很悲观,认为什么时候都会出问题,无论做什么都会加锁。
2. 乐观锁
- 很乐观,认为什么时候都不会出问题,所以不会上锁。更更新数据的时候回去判断一下,在此期间是否有人修改过这个数据。
- 获取version
- 更新的时候比较version
3. Redis实现乐观锁
3.1 正常执行
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
3.2 测试多线程
测试多线程修改值,使用watch可以当作redis的乐观锁操作。
第一个窗口
127.0.0.1:6379> watch 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 # 执行之前,另外一个线程修改了这个值,在执行exec,这个时候事务会失败 (nil)
第二个窗口
127.0.0.1:6379> set money 100 OK
解决:获取最新的值
# 1. 先解锁 127.0.0.1:6379> unwatch # OK # 2. 在加锁,获取最新的值 127.0.0.1:6379> watch money OK # 3. 开启事务 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) 40