在项目中要用到分布式锁,之前都是用jedis去实现的,有很多细节方面都有可能出问题,然后在了解到了redisson之后,决定使用这个成熟的框架去实现分布式锁。
首先引入jar包,除了spring boot的相关jar包,只引这一个就够了
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.9.1</version>
</dependency>
创建一个redis配置类
@Data
@ConfigurationProperties(prefix ="redisson")
public class RedissonProperties {
/** redis地址 */
private String address;
/** 密码 */
private String password;
// 毫秒
private int timeout=10000;
private int database=0;
private int connectionPoolSize=150;
private int connectionMiniumIdleSize=10;
// 毫秒
private int scanInterval=2000;
}
在配置文件中,声明相对应的属性
#redisson的redis地址 单点
redisson.address=redis://redis-master.fn-data-platform:6379
redisson.password=agnYqD2fih
之后写一个config把redisson注册到spring中就可以了,这里使用的是单点redis模式,建议用于锁的redis和用于缓存的redis要分开,用于锁的要保证HA。
/**
* @program: common-info
* @description: redisson 配置类
* @author: lvqiushi
* @create: 2019-05-05 10:41
**/
@Configuration
@EnableConfigurationProperties({ RedissonProperties.class })
public class RedissonConfig {
@Autowired
private RedissonProperties redissonProperties;
@Bean
@ConditionalOnProperty(name = "redisson.address")
public RedissonClient redissonSingle(){
Config config = new Config();
SingleServerConfig serverConfig = config.useSingleServer()
.setAddress(redissonProperties.getAddress())
.setTimeout(redissonProperties.getTimeout())
.setDatabase(redissonProperties.getDatabase())
.setConnectionPoolSize(redissonProperties.getConnectionPoolSize())
.setConnectionMinimumIdleSize(redissonProperties.getConnectionMiniumIdleSize())
.setKeepAlive(true);
if(StringUtils.isNotEmpty(redissonProperties.getPassword())){
serverConfig.setPassword(redissonProperties.getPassword());
}
return Redisson.create(config);
}
}
配置完成后,即可开始使用,我写了一个很简单的包装服务类,只用到了RLock可重入锁,redisson的锁有很多种类型,这个大家自己去学习了解。
/**
*
* @description: 分布式锁相关服务接口
* @author: xiucai
* @create: 2019-05-05
*
**/
public interface DistributedLock {
/**
* @Description: 使用默认超时时间设置锁 默认时间30s
* @param lockKey
* @return: org.redisson.api.RLock
* @Author: lvqiushi
* @Date: 2019-05-05
*/
RLock lock(String lockKey);
/**
* @Description: 为锁设置超时时间
* @param lockKey
* @param leaseTime 锁自动失效时间 单位:豪秒
* @return: org.redisson.api.RLock
* @Author: lvqiushi
* @Date: 2019-05-05
*/
RLock lock(String lockKey, int leaseTime);
/**
* @Description: 尝试获取锁,在等待时间内获取到锁则返回true,否则返回false,如果获取到锁,在指定超时时间释放锁
* @param lockKey
* @param waitTime 等到最大时间,强制获取锁
* @param leaseTime 锁自动失效时间
* @return: boolean
* @Author: lvqiushi
* @Date: 2019-05-05
*/
boolean tryLock(String lockKey, int waitTime, int leaseTime);
/**
* @Description: 释放锁
* @param lockKey
* @return: void
* @Author: lvqiushi
* @Date: 2019-05-05
*/
void unlock(String lockKey);
}
然后是服务接口实现类,在实现类中引入在config中声明的bean
@Slf4j
@Component
public class DistributedLockImpl implements DistributedLock {
@Autowired
private RedissonClient redissonClient;
@Override
public RLock lock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock();
return lock;
}
@Override
public RLock lock(String lockKey, int leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(leaseTime, TimeUnit.MILLISECONDS);
return lock;
}
@Override
public boolean tryLock(String lockKey, int waitTime, int leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime,leaseTime,TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
log.error("", e);
}
return false;
}
@Override
public void unlock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.unlock();
}
}