redisson实现分布式锁
前言
还是在工作中遇到的问题:
1:新增商铺信息时,同一个商铺有多条信息。
异步的情况,根据商铺名和商铺地址作为唯一条件,不加分布式锁就会有重复的商铺信息。
2:代码要发布到云化环境(redis集群) & 一体机环境(redis单例)
使用ConditionalOnProperty注解
一、引入redisson依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.16.2</version>
</dependency>
二、redis 配置
spring:
# redis单例配置
# redis:
# host: 127.0.0.1
# port: 6379
# password: 123456
# serializer: json
# jedis:
# pool:
# max-active: 20
# max-idle: 20
# max-wait: 2000ms
# time-between-eviction-runs: 3000
# redis集群配置
redis:
cluster:
nodes: xxx.xxx.xxx.xxx:pppp,xxx.xxx.xxx.xxx:pppp,xxx.xxx.xxx.xxx:pppp,xxx.xxx.xxx.xxx:pppp
password: 123456
serializer: json
jedis:
pool:
max-active: 20
max-idle: 20
max-wait: 2000ms
time-between-eviction-runs: 30000
三、redisson 配置
1.集群配置
代码如下(示例):
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Slf4j
@Configuration
@ConditionalOnProperty(name = "spring.redis.cluster.nodes")
public class MyRedissonClusterConfig {
private static final String REDIS_SSH_URL = "redis://";
@Value(value = "${spring.redis.cluster.nodes}")
private String host;
@Value(value = "${spring.redis.password}")
private String password;
/**
* 所有对redisson的使用都是通过RedissonClient来操作的
*/
@Bean(destroyMethod = "shutdown")
public RedissonClient redisson() {
log.info("redisson启动,加载集群");
// 1. 创建配置
Config config = new Config();
// 一定要加redis://
String[] hostArr = host.split(",");
String[] newHostArr = new String[hostArr.length];
for (int i = 0; i < hostArr.length; i++) {
newHostArr[i] = REDIS_SSH_URL + hostArr[i];
}
config.useClusterServers().addNodeAddress(newHostArr);
config.useClusterServers().setPassword(password);
// 2. 根据config创建出redissonClient实例
return Redisson.create(config);
}
}
2.单例配置
代码如下(示例):
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Slf4j
@Configuration
@ConditionalOnProperty(name = "spring.redis.host")
public class MyRedissonSingleConfig {
private static final String REDIS_SSH_URL = "redis://";
@Value(value = "${spring.redis.host}")
private String host;
@Value(value = "${spring.redis.port}")
private String port;
@Value(value = "${spring.redis.password}")
private String password;
/**
* 所有对redisson的使用都是通过RedissonClient来操作的
*
*/
@Bean(destroyMethod = "shutdown")
public RedissonClient redisson() {
log.info("redisson启动,加载单例");
// 1. 创建配置
Config config = new Config();
// 一定要加redis://
config.useSingleServer().setAddress(REDIS_SSH_URL+ host + ":" + port);
config.useSingleServer().setPassword(password);
// 2. 根据config创建出redissonClient实例
return Redisson.create(config);
}
}
该处使用的url网络请求的数据。
四、分布式锁使用-业务层demo
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
@Autowired
private RedissonClient redissonClient;
@GetMapping("test/lock")
public String testLock() {
RLock lock = redissonClient.getLock("123");
try {
//加锁10s,不设置加密狗,不搞死锁。
boolean b = lock.tryLock(10, TimeUnit.SECONDS);
if (b) {
//todo 这里写业务逻辑
return "123";
}
} catch (InterruptedException e) {
e.printStackTrace();
log.error("分布式锁异常了," + e.getMessage());
} finally {
lock.unlock();
}
return null;
}