Redis-分布式锁
一、Redis实现原理
redis实现分布式锁主要利用redis的setnx命令。setnx是set if not exist(不存在就set)的简写。
- 获取锁:set lock value nx(互斥) ex(时间) 10。
- 释放锁:del key
二、锁有效时长控制
1.根据业务时间评估
- 该方法有很大的弊端,因为业务执行的时间都是有一定的抖动的,无法精确地控制。非常不建议。
2.给锁续期-redisson实现分布式锁
- 加锁&续期:基于redis的setnx命令实现,加锁成功后会创建一个watch dog,每1/3的releaseTime(30s)给锁续期一次。释放锁时,通知watch dog停止监听线程。
- 释放锁:手动释放,同时通知watch dog停止对该分布式锁的监听。
- 获取锁:与通过命令直接get不同,redisson会通过while死循环不停尝试获取锁,当达到一定阈值后仍然没有获取到锁则放弃。
public void redisLock(){
//通过redisson获取锁
RLock lock = redissonClient.getLock("hansalive");
//尝试获取锁 param 获取锁的最大等待时间,锁自动释放时间,单位
boolean isLock = lock.tryLock(10,10, TimeUnit.SECONDS);
//判断是否获取成功
if (isLock) {
try {
System.out.println("业务流程");
} finally {
//释放锁
lock.unlock();
}
}
}
2.1 redisson分布式锁的可重入性
在同一线程中重新调用分布式锁是可以的,当获取锁时,会判断当前获取锁的线程和持有锁的线程是否为同一个,如果是同一线程则获取锁成功。所以下面代码中的调用add2获取锁是可以获取到的。
public void add1() {
RLock lock = redissonClient.getLock("hansalive");
boolean isLock = lock.tryLock();
//调用add2再次获取锁
add2();
lock.unlock();
}
public void add2 () {
RLock lock = redissonClient.getLock("hansalive")
boolean isLock = lock.tryLock();
lock.unlock()
}
}
2.2 redisson主从一致性
redis集群读写分离,如何保证数据一致性。
- 红锁(RedLock)
不能只在一个redis实例上创建锁,应该是在多个redis上创建(n/2+1)- 实现比较复杂
- 性能差
- 运维繁琐,官方也不建议直接使用红锁来解决一致性问题。
- 强一致性建议解决方案使用zookeeper提供的cp思想的分布式锁。