Java使用Redis来实现分布式锁
在单节点服务中,我们可以使用
synchronized
来保证同一时间内只允许一个线程执行限定的代码块。但是如果我们是多节点服务呢,因为synchronized
是针对服务内部的,其他服务是无法受到他的干预的。那么如何保证多个节点在同一时间内只允许一个节点中的一个线程去访问这个代码块呢?使用
分布式锁
!!!本文使用
Redisson
来操作Redis
并实现分布式锁
Redisson
官网:https://github.com/redisson/redisson/tree/redisson-3.16.8
-
引入依赖
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.16.8</version> </dependency>
-
创建
RedissonConfig
配置类@ConfigurationProperties(prefix = "spring.redis") @Configuration @Data public class RedissonConfig {// 主机名private String host;// 端口private String port;// 使用那个数据库private Integer database;@Beanpublic RedissonClient redissonClient(){Config config = new Config();// 使用单机Redis服务config.useSingleServer()// use "rediss://" for SSL connection.setAddress(String.format("redis://%s:%s",host,port)).setDatabase(database);return Redisson.create(config);} }
-
创建配置文件
# Redis 配置 spring.redis.host=xxx spring.redis.port=xxx spring.redis.database=xxx
-
在业务代码中添加分布式锁
// 注入我们的RedissonClient @Autowired private RedissonClient redissonClient;{// 指定一个key来获取锁,如果是需要按不同的情况加锁的话,这样可以使用变量RLock lock = redissonClient.getLock("LOCK_NAME");try{lock.tryLock(long waitTime, long leaseTime, TimeUnit unit);//... 业务逻辑}catch (InterruptedException ex) {ex.printStackTrace();}finally{// 判断是否由当前线程持有锁 if (lock.isHeldByCurrentThread()) {// 释放锁lock.unlock();}} }
tryLock
尝试获取锁 获取成功返回true 获取失败返回falsewaitTime
尝试获取锁的等待时间,超过不再继续获取leaseTime
锁的持有时间,业务代码的执行时间如果超过该时间则抛出异常- 可以设置为null 或者 -1 表示业务执行多久占用多久,这里其实使用了
看门狗
的一个机制,默认的持有时间是30秒,如果超时未执行完成,看门狗
会为我们自己续期一次。已保证业务代码执行完成。
- 可以设置为null 或者 -1 表示业务执行多久占用多久,这里其实使用了
unit
时间单位