Redis Java Client选型-Jedis Lettuce Redisson
最常用的可重入锁(Reentrant Lock) 先写个单元测试试一下
public class RedisLockTest {
private RedissonClient redissonClient;
//请求的key
private static final String demo ="u001";
//模拟短时间内的并发请求量
private static final int threadNum =5;
@Before
public void init(){
Config config = new Config();
config.useSingleServer().setAddress("redis://120.78.144.70:6379");
this.redissonClient = Redisson.create(config);
System.out.println(Thread.currentThread().getName()+"是否存在key"+redissonClient.getLock(demo).isExists());
}
private class UserRequest implements Runnable{
private CountDownLatch cdl;
public UserRequest(CountDownLatch latch){
this.cdl=latch;
}
@Override
public void run() {
try {
if (redissonClient.getLock(demo).tryLock(0L,-1L, TimeUnit.SECONDS)) {
System.out.println(Thread.currentThread().getName()+"获取锁成功");
Thread.sleep(5000);
redissonClient.getLock(demo).unlock();
System.out.println(Thread.currentThread().getName()+"释放锁成功");
}else{
System.out.println(Thread.currentThread().getName()+"获取锁失败"+"是否存在key"+redissonClient.getLock(demo).isExists());
}
}catch (Exception e) {
e.printStackTrace();
}finally {
//倒计时计数一次
cdl.countDown();
}
}
}
@Test
public void testRedissonLock(){
CountDownLatch cdl=new CountDownLatch(threadNum);
Executor executor = Executors.newFixedThreadPool(threadNum);
try{
for (int i =0; i< threadNum; i++) {
if(i==2){
//模拟在业务代码没执行完毕时另一个线程获取锁
Thread.sleep(1500);
}
executor.execute(new UserRequest(cdl));
}
//阻塞主线程,等待所有的子线程执行完毕
cdl.await();
}catch (Exception e){
e.printStackTrace();
}
}
}
分布式锁的实现分析参考
https://www.jianshu.com/p/a8b3473f9c24
比较关注的一个参数一个是过期时间,一个是定时续约过期时间
通过阅读源码知道lesstime参数决定是否续约
private <T> RFuture<Long> tryAcquireAsync(long leaseTime, TimeUnit unit, final long threadId) {
if (leaseTime != -1L) {
return this.tryLockInnerAsync(leaseTime, unit, threadId, RedisCommands.EVAL_LONG);
} else {
RFuture<Long> ttlRemainingFuture = this.tryLockInnerAsync(this.commandExecutor.getConnectionManager().getCfg().getLockWatchdogTimeout(), TimeUnit.MILLISECONDS, threadId, RedisCommands.EVAL_LONG);
ttlRemainingFuture.addListener(new FutureListener<Long>() {
public void operationComplete(Future<Long> future) throws Exception {
if (future.isSuccess()) {
Long ttlRemaining = (Long)future.getNow();
if (ttlRemaining == null) {
RedissonLock.this.scheduleExpirationRenewal(threadId);
}
}
}
});
return ttlRemainingFuture;
}
}
总结一点
if(leaseTime==-1L){
开启自动续期的定时任务,不断重置过期时间为lockWatchdogTimeout
定时任务的频率为lockWatchdogTimeout配置时间的1/3
}else{
不自动续期
设置过期时间为leaseTime
}
所有属性介绍 https://yq.aliyun.com/articles/551640/
其他锁类型的锁参考
(联锁,红锁,读写锁,信号量,可过期性信号量)
https://blog.csdn.net/l1028386804/article/details/73523810