转自尚硅谷------阳哥
1.redis的分布式锁
加锁:
stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK_KEY, value);//setnx
释放锁:
stringRedisTemplate.delete(REDIS_LOCK_KEY);//释放锁
2.出异常无法释放锁,则强制完成删锁,防止阻塞
也就是把释放锁加入finally{}代码块中
3.加过期时间,处理服务器突发宕机
stringRedisTemplate.expire(REDIS_LOCK_KEY,10L, TimeUnit.SECONDS);
4.设置key+过期时间分开了,必须要合并成一行具备原子性:
加锁和设置过期时间合并为同一语句保证原子性:
Boolean lockFlag = stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK_KEY, value,10L, TimeUnit.SECONDS);
5.★张冠李戴,删了其他线程的锁,解决:
先判断再删除
finally {
if (value.**equalsIgnoreCase**(stringRedisTemplate.opsForValue().get(REDIS_LOCK_KEY))){
stringRedisTemplate.delete(REDIS_LOCK_KEY);//释放锁
}
6.finally块的判断+del删除操作不是原子性的
不用lua脚本,如何实现(实际工作中100%用lua!)???
解决:redis事务版:
finally {
while (true)
{
stringRedisTemplate.watch(REDIS_LOCK_KEY); //加事务,乐观锁
if (value.equalsIgnoreCase(stringRedisTemplate.opsForValue().get(REDIS_LOCK_KEY))){
stringRedisTemplate.setEnableTransactionSupport(true);
stringRedisTemplate.multi();//开始事务
stringRedisTemplate.delete(REDIS_LOCK_KEY);
List<Object> list = stringRedisTemplate.exec();
if (list == null) {
//如果等于null,就是没有删掉,删除失败,再回去while循环那再重新执行删除
continue;
}