1. 最基础的应用
String lockKey="lockKey";
//使用setnx命令加锁
stringRedisTemplate.opsForValue().setIfAbsent(lockKey,value);
...
//执行业务逻辑代码完成后释放锁
stringRedisTemplate.delete(lockKey);
存在的问题:
执行业务逻辑代码时出现异常,导致锁不能被释放。
解决方案:
加try finally语句,执行出现异常也释放锁。
存在的问题:
如果在执行代码的时候web服务器宕机,锁还是不能被释放。
解决方案:
设置过期时间:
//如果10s后还没释放锁,就强制释放锁
stringRedisTemplate.expire(lockKey,10,TimeUnit.SECONDS);
存在的问题:
setnx和expire不是原子块操作
解决方案:
//使用对应的原子命令
stringRedisTemplate.opsForValue.setIfAbsent(key,value,timeout,timeunit);
存在的问题:
假设超时时间是10s,其中,A需要执行15s才能完成,B需要执行8s,C需要执行5s。那么,当A执行10s后,锁被自动释放了,但是A还在继续执行,此时,B拿到了锁,过5s后,A执行完了,然后A去执行delete(key)释放锁的时候,释放了B持有的锁(也就是删掉了redis中的一个KV而已。。),这时候C又持有锁了(又setnx成功了),过3s后,B执行完了,然后把C的锁释放了,就这样循环地释放别人的锁……
解决方案:
value存成随机的,或者和当前执行用户有关的,每个用户在释放锁的时候首先判断此时的value是不是自己添加的,以此达到只能释放自己的锁的目的。
存在的问题:
过期时间写死很容易设置不合理
解决方案:
设置分线程对锁续命,如果没有执行完,就延长持有锁的时间。
2. Redisson
用法:
RLock redissonLock=redisson.getLock(lockKey);
redissonLock.lock();
redissonLock.unlock();
后台线程每隔10s(1/3的时长)检查是否还持有锁。
存在的问题:
redis主从同步
redis主从同步好像是异步的?假设主节点一下子挂了,那么从节点还没有这个锁的信息
解决方案:
来自网友:多节点redis实现的分布式锁算法(RedLock),有效防止单点故障。
redis分布式锁的优势在于性能,zookeeper等的可靠性比redis高。
3. RedLock
待补充……