<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.13.6</version>
</dependency>
spring:
redis:
cluster:
nodes:
- 192.168.119.101:6111
- 192.168.119.101:6112
- 192.168.119.101:6113
- 192.168.119.101:6114
- 192.168.119.101:6115
- 192.168.119.101:6116
max-attempts: 3
lettuce:
pool:
max-active: 1500
max-wait: 5000
max-idle: 500
min-idle: 100
shutdown-timeout: 1000
password: mypassword
timeout: 60000
port: 6111
host: 192.168.119.101
@Data
@Configuration
@ConfigurationProperties(prefix = "spring.redis")
@NoArgsConstructor
public class RedisProperties {
private int database = 0;
private String password;
private Duration timeout;
private String host="localhost";
private Integer port = 6379;
private RedisProperties.Cluster cluster;
private final RedisProperties.Jedis jedis = new RedisProperties.Jedis();
@Getter
@NoArgsConstructor
public static class Jedis {
private final RedisProperties.Pool pool = new RedisProperties.Pool();
}
@Data
@NoArgsConstructor
public static class Cluster {
private List<String> nodes;
private String password;
private Integer maxAttempts;
}
@Data
@NoArgsConstructor
public static class Pool {
private int maxIdle = 8;
private int minIdle = 0;
private int maxActive = 8;
private Duration maxWait = Duration.ofMillis(-1L);
}
}
@Slf4j
@Configuration
public class RedissonConfig extends CachingConfigurerSupport {
private final String REDISSON_PREFIX = "redis://";
@Autowired
private RedisProperties redisProperties;
@Bean(destroyMethod="shutdown")
RedissonClient redisson() throws IOException {
Config config = new Config();
/*config.useSingleServer().setAddress("192.168.43.129:6379");*/
//redisson版本是3.5,集群的ip前面要加上“redis://”,不然会报错,3.2版本可不加
List<String> clusterNodes = redisProperties.getCluster().getNodes().stream()
/*.map(m->String.join("","redis://", m))*/
.map(m->REDISSON_PREFIX.concat(m))
.collect(Collectors.toList());
ClusterServersConfig clusterServersConfig = config.useClusterServers()
.addNodeAddress(clusterNodes.toArray(new String[clusterNodes.size()]));
clusterServersConfig.setPassword(redisProperties.getPassword());//设置密码
//redis-cli存数据时的序列化策略是string,但是redission的默认序列化策略是Jackson JSON 编码
config.setCodec(new StringCodec());
return Redisson.create(config);
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
RedisSerializer<Object> jackson2JsonRedisSerializer = redisSerializer();
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
template.setKeySerializer(stringRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
// 初始化 RedisTemplate 序列化完成
template.afterPropertiesSet();
return template;
}
@Bean
public RedisSerializer<Object> redisSerializer() {
//创建JSON序列化器
//GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(objectMapper);
return serializer;
}
/**
* 对hash类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}
/**
* 对redis字符串类型数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForValue();
}
/**
* 对链表类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}
/**
* 对无序集合类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}
/**
* 对有序集合类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
//设置Redis缓存有效期为1天
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())).entryTtl(Duration.ofDays(1));
return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
}
@Bean
public JedisPoolConfig jedisPoolConfig() {
RedisProperties.Pool pool = redisProperties.getJedis().getPool();
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(pool.getMaxActive());
jedisPoolConfig.setMaxIdle(pool.getMaxIdle());
jedisPoolConfig.setMinIdle(pool.getMinIdle());
jedisPoolConfig.setMaxWait(pool.getMaxWait());
return jedisPoolConfig;
}
@Bean
public JedisPool jedisPool(JedisPoolConfig jedisPoolConfig) {
log.info("=====创建JedisPool连接池=====");
if(StringUtils.isNotEmpty(redisProperties.getPassword())) {
return new JedisPool(jedisPoolConfig, redisProperties.getHost(), redisProperties.getPort(),
redisProperties.getTimeout().getNano(), redisProperties.getPassword());
}
return new JedisPool(jedisPoolConfig, redisProperties.getHost(), redisProperties.getPort(),
redisProperties.getTimeout().getNano());
}
@Bean
public JedisCluster jedisCluster(){
RedisProperties.Cluster cluster = redisProperties.getCluster();
Set<HostAndPort> set = new HashSet<>();
HostAndPort hp = null;
List<String> nodes =cluster.getNodes();
if(nodes!=null&&nodes.size()>0){
for(int i=0;i<nodes.size();i++){
String[] hostPort = nodes.get(i).split(":");
if(hostPort!=null&&hostPort.length>0){
hp = new HostAndPort(hostPort[0],Integer.valueOf(hostPort[1]));
set.add(hp);
}
}
}
JedisCluster jedisCluster = new JedisCluster(set, redisProperties.getTimeout().getNano(),
redisProperties.getTimeout().getNano(), cluster.getMaxAttempts(), redisProperties.getPassword(), jedisPoolConfig());
/* JedisCluster jedisCluster = new JedisCluster(set);*/
return jedisCluster;
}
/*@Bean
RedisClusterCommands<String, String> redisCommands() {
List<RedisURI> uriList = new ArrayList<>();
redisConfigProperties.getCluster().getNodes().forEach(node -> {
String[] addrStr = node.split(":");
String host = addrStr[0];
int port = Integer.parseInt(addrStr[1]);
RedisURI redisUri = RedisURI.Builder.redis(host).withPort(port).build();
uriList.add(redisUri);
});
RedisClusterClient redisClient = RedisClusterClient.create(uriList);
StatefulRedisClusterConnection<String, String> connection = redisClient.connect();
RedisClusterCommands<String, String> syncCommands = connection.sync();
return syncCommands;
}*/
}
@Slf4j
@Component
public class DistributedRedisLock {
@Autowired
private RedissonClient redissonClient;
// 加锁
public Boolean lock(String lockName) {
if (redissonClient == null) {
log.info("DistributedRedisLock redissonClient is null");
return false;
}
try {
RLock lock = redissonClient.getLock(lockName);
// 锁10秒后自动释放,防止死锁
lock.lock(10, TimeUnit.SECONDS);
log.info("Thread [{}] DistributedRedisLock lock [{}] success", Thread.currentThread().getName(), lockName);
// 加锁成功
return true;
} catch (Exception e) {
log.error("DistributedRedisLock lock [{}] Exception:", lockName, e);
return false;
}
}
// 释放锁
public Boolean unlock(String lockName) {
if (redissonClient == null) {
log.info("DistributedRedisLock redissonClient is null");
return false;
}
try {
RLock lock = redissonClient.getLock(lockName);
lock.unlock();
log.info("Thread [{}] DistributedRedisLock unlock [{}] success", Thread.currentThread().getName(), lockName);
// 释放锁成功
return true;
} catch (Exception e) {
log.error("DistributedRedisLock unlock [{}] Exception:", lockName, e);
return false;
}
}
}
@Slf4j
@RestController
public class IndexController {
@Autowired
private RedissonClient redissonClient;
@Autowired
private RedisTemplate redisTemplate;
@Resource
ValueOperations<String, Object> valueOperations;
@Autowired
private JedisPool jedisPool;
@Autowired
private JedisCluster jedisCluster;
@GetMapping("index")
public Object index(){
@Cleanup Jedis jedis = jedisPool.getResource();
jedis.set("jedis","jedis");
jedisCluster.set("jedisCluster","jedisCluster");
valueOperations.set("name","sgh");
return valueOperations.get("name");
}
@GetMapping("test1")
public String test1(){
RBucket<String> key = redissonClient.getBucket("newday");
key.set("新的数据");
System.out.println("获取到新存入的数据:"+key.get());
// 获取字符串格式的数据
RBucket<String> keyObj = redissonClient.getBucket("myname");
String s = keyObj.get();
System.out.println("获取到昨天存入的数据:"+s);
return s;
}
private final String LOCK = "LOCK";
@Autowired
private DistributedRedisLock distributedRedisLock;
// 测试不释放锁
@GetMapping("/testLock")
public void testLock() {
for (int i = 0; i < 5; i++) {
new Thread(() -> {
distributedRedisLock.lock(LOCK);
}).start();
}
}
// 实际业务开发使用分布式锁的方式
@PostMapping
public void post() {
try {
if (distributedRedisLock.lock(LOCK)) {
// 业务逻辑
log.info("开始业务逻辑");
} else {
// 处理获取锁失败的逻辑
log.info("获取锁失败");
}
} catch (Exception e) {
log.error("处理异常:", e);
} finally {
distributedRedisLock.unlock(LOCK);
}
}
}