大部分互联网公司实现分布式锁原理
/**
* 分布式锁底层实现原理
* @return
*/
@GetMapping("distributedLock")
public Object distributedLock(){
String lockKey = "distributedLockKey";
//给每个线程都设置一个唯一标识,避免出现程序执行的时间超过设置的过期时间,导致其他线程删除了自己的锁
String clientId = UUID.randomUUID().toString();
try {
//添加过期时间保证线程运行到一半的时候,程序崩了,导致缓存中的key一直存在
Boolean result = redisTemplate.opsForValue().setIfAbsent(lockKey, clientId, 30, TimeUnit.SECONDS);
if (!result) {
return "error_code";
}
// Todo 实现业务逻辑
redisTemplate.opsForValue().set(TestConstant.KEY_TEST,String.valueOf(System.currentTimeMillis()));
} finally {
//判断是不是自己的线程删除自己的锁
if (clientId.equals(redisTemplate.opsForValue().get(lockKey))) {
redisTemplate.delete(lockKey);
}
}
//Todo 当前代码未实现锁续命功能,锁续命功能:由于程序执行时间可能超过设置缓存中锁的过期时间,导致后续一部分业务未执行,一直被其他线程抢占,需要对锁进行续命,但是由于续命的时间不好确定,这个时候就需要单独开启子线程,定时任务不断的去判断当前锁,还在不在,如果不在了,说明业务已经执行完成了,如果还在,重新设置过期时间,一般而言,定时任务的时间为缓存设置的过期时间三分之一就可以了。
return "end";
}
基于redisson实现高并发分布式锁
引入依赖:
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.6.5</version>
</dependency>
启动类中注入bean对象:
@Bean
public Redisson redisson() {
// 此为单机模式
Config config = new Config();
config.useSingleServer().setAddress("redis://localhost:6379").setDatabase(0);
return (Redisson) Redisson.create(config);
}
实现分布式:
@Autowired
RedisTemplate redisTemplate;
@Autowired
private Redisson redisson;
/**
* 基于redisson实现高并发分布式锁
* @return
*/
@GetMapping("highConcurrencyDistributedLock")
public Object highConcurrencyDistributedLock(){
RLock redissonLock = redisson.getLock(TestConstant.HIGH_CONCURRENCY_DISTRIBUTED_LOCK);
try {
//加锁,实现了key设置,过期时间,锁续命功能
redissonLock.lock(); //redisTemplate.opsForValue().setIfAbsent(lockKey, clientId, 30, TimeUnit.SECONDS);
// Todo 实现业务逻辑
redisTemplate.opsForValue().set(TestConstant.KEY_TEST,String.valueOf(System.currentTimeMillis()));
} finally {
//释放锁
redissonLock.unlock();
}
return redisTemplate.opsForValue().get(TestConstant.KEY_TEST);
}