什么是Redisson?
俗话说他就是看门狗,看门狗机制是一种用于保持Redis连接活跃性的方法,通常用于分布式锁的场景。看门狗的工作原理是:当客户端获取到锁之后,会对Redis中的一个特定的键设置一个有限的过期时间,然后每隔一段时间(默认是15秒),客户端会对这个键“续约”,即重新设置它的过期时间,以此来保持锁的持有状态,防止锁因为某些原因(如客户端崩溃或网络问题)而被释放。
以下是核心实战部分
配置文件读取
@ConfigurationProperties(
prefix = "spring.redis.redisson"
)
@Data
public class RedissonProperties {
/**
* key前缀
*/
private String keyPrefix;
/**
* 拿锁等待时间(毫秒)
*/
private long waitTime = 10000;
/**
* 默认ttl时间(毫秒)
*/
private long leaseTime = 60000;
@Value("${spring.redis.redisson.config.clusterServersConfig.nodeAddresses}")
private String nodeAddresses;
@Value("${spring.redis.redisson.config.clusterServersConfig.scanInterval}")
private Integer scanInterval;
@Value("${spring.redis.redisson.config.threads}")
private Integer threads;
@Value("${spring.redis.redisson.config.nettyThreads}")
private Integer nettyThreads;
@Value("${spring.redis.redisson.config.transportMode}")
private String transportMode;
}
yml文件
spring:
##redis集群配置
redis:
database: 0
timeout: 5000ms
redisson:
config:
clusterServersConfig:
nodeAddresses: redis://10.xxx.xx.x1:6379,redis://10.xxx.xx.x2:6379,redis://10.xxx.xx.x3:6379
scanInterval: 1000
nettyThreads: 0
threads: 0
transportMode: NIO
key-prefix: test:key
lease-time: 80000
wait-time: 50000
redisson自动配置类
@Configuration
@ConditionalOnClass({Redisson.class})
@EnableConfigurationProperties({RedissonProperties.class})
@Slf4j
public class RedissonAutoConfiguration {
@Bean
@ConditionalOnMissingBean({RedisConnectionFactory.class})
public RedissonConnectionFactory redissonConnectionFactory(RedissonClient redisson) {
return new RedissonConnectionFactory(redisson);
}
@Bean(
destroyMethod = "shutdown"
)
@ConditionalOnMissingBean({RedissonClient.class})
public RedissonClient redisson(RedissonProperties redissonProperties) throws IOException {
Config config = new Config();
config.useClusterServers().addNodeAddress(redissonProperties.getNodeAddresses().split(","))
.setScanInterval(redissonProperties.getScanInterval());
config.setThreads(redissonProperties.getThreads())
.setNettyThreads(redissonProperties.getNettyThreads())
.setTransportMode(TransportMode.valueOf(redissonProperties.getTransportMode()));
return Redisson.create(config);
}
@Bean
@ConditionalOnMissingBean(
name = {"redisTemplate"}
)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
redis的缓存类实现
@Service
public class RedisCache {
@Autowired
private RedissonClient redisson;
@Autowired
private RedissonProperties redissonProperties;
/**
* 缓存
*
* @param key 缓存key
* @param <T>
* @return 缓存返回值
*/
public <T> T get(String key) {
RBucket<T> bucket = redisson.getBucket(getKey(key));
return bucket.get();
}
/**
* 以string的方式读取缓存
*
* @param key 缓存key
* @return 缓存返回值
*/
public String getString(String key) {
RBucket<String> bucket = redisson.getBucket(getKey(key), StringCodec.INSTANCE);
return bucket.get();
}
/**
* 以string的方式保存缓存(与其他应用共用redis时需要使用该函数)
*
* @param key 缓存key
* @param value 缓存值
* @param expiredTime 缓存过期时间
*/
public void putString(String key, String value, long expiredTime) {
RBucket<String> bucket = redisson.getBucket(getKey(key), StringCodec.INSTANCE);
bucket.set(value, expiredTime, TimeUnit.MILLISECONDS);
}
/**
* 如果不存在则写入缓存(string方式,不带有redisson的格式信息)
*
* @param key 缓存key
* @param value 缓存值
* @param expiredTime 缓存过期时间
*/
public boolean putStringIfAbsent(String key, String value, long expiredTime) {
RBucket<String> bucket = redisson.getBucket(getKey(key), StringCodec.INSTANCE);
return bucket.trySet(value, expiredTime, TimeUnit.MILLISECONDS);
}
/**
* 设置缓存
*
* @param key 缓存key
* @param value 缓存值
* @param expiredTime 缓存过期时间
* @param <T> 类型
*/
public <T> void put(String key, T value, long expiredTime) {
RBucket<T> bucket = redisson.getBucket(getKey(key));
bucket.set(value, expiredTime, TimeUnit.MILLISECONDS);
}
/**
* 如果不存在则设置缓存
*
* @param key 缓存key
* @param value 缓存值
* @param expiredTime 缓存过期时间
* @param <T> 类型
*/
public <T> void putIfAbsent(String key, T value, long expiredTime) {
RBucket<T> bucket = redisson.getBucket(getKey(key));
bucket.trySet(value, expiredTime, TimeUnit.MILLISECONDS);
}
/**
* 移除缓存
*
* @param key
*/
public void remove(String key) {
redisson.getBucket(getKey(key)).delete();
}
/**
* 判断缓存是否存在
*
* @param key
* @return
*/
public boolean exists(String key) {
return redisson.getBucket(getKey(key)).isExists();
}
private String getKey(String key) {
return StringUtils.format("{0}:{1}", redissonProperties.getKeyPrefix(), key);
}
获取和释放分布式锁接口
DistributedLock
/**
* get分布式锁
* @param lockKey
* @param requestId
* @param expireTime
* @return
*/
public boolean getDistributedLock(String lockKey, String requestId, long expireTime);
/**
* remove分布式锁
* @param lockKey
* @param requestId
* @return
*/
public boolean removeDistributedLock(String lockKey, String requestId);
实现DistributedLock的实现类逻辑
@Service
public class RedisDistributedLocker implements DistributedLocker {
private static final Logger logger = LoggerFactory.getLogger(RedisDistributedLocker.class);
@Autowired
private RedissonClient redisson;
@Autowired
private RedissonProperties redissonProperties;
public boolean getDistributedLock(String lockKey, String flagId, long expireTime) {
boolean success;
try {
if (expireTime == 0) {
expireTime = redissonProperties.getLeaseTime();
}
lockKey = StringUtils.format("{0}:{1}", redissonProperties.getKeyPrefix(), lockKey);
RLock locker = redisson.getLock(lockKey);
success = locker.tryLock(redissonProperties.getWaitTime(), expireTime, TimeUnit.MILLISECONDS);
} catch (Exception e) {
success = false;
logger.error(StringUtils.format("获取分布式锁失败,lockKey={0}, flagId={1}, expirTime={2}", lockKey, flagId, expireTime), e);
}
return success;
}
public boolean releaseDistributedLock(String lockKey, String flagId) {
boolean success = false;
try {
lockKey = StringUtils.format("{0}:{1}", redissonProperties.getKeyPrefix(), lockKey);
RLock locker = redisson.getLock(lockKey);
if (locker.isHeldByCurrentThread()) {
locker.unlock();
success = true;
}
} catch (Exception e) {
success = false;
logger.error(StringUtils.format("分布式锁失败,lockKey={0}, flagId={1}", lockKey, flagId), e);
}
return success;
}
在需要的业务场景下使用 以下为伪代码
try {
boolean ock = distributedLocker.getDistributedLock(lockKey, flagId, 9000L);
if (!ock) {
return;
}
// 实现自己的业务逻辑。。。。。。。。。。。。。。。。。。。。。。。。。
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
} finally {
distributedLocker.releaseDistributedLock(lockKey, flagId);
}
以上的是分布式锁之RedissonLock 若需完整代码 可识别二维码后 给您发代码。