<!-- 开启boot对redis的支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 开启redis对管理session-->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
代码如下(示例):集群或哨兵模式部署配置请参考我的上一篇文章《Redis的部署安装以及集群哨兵模式》
spring:
redies: #redies缓存
host: 192.168.1.233
port: 6397
password:
timeout: 60000 #连接超时时间(毫秒)
database: 0 # Redis数据库索引(默认为0)
lettuce:
shutdown-timeout: 100 #在关闭客户端连接之前最大等待任务结束时间 默认100ms
pool:
max-active: 8 #连接池最大连接数
min-idle: 2 #最小空闲数
max-idle: 20 #最大空闲数
max-wait: 60000 #最大建立连接等待时间
#集群或哨兵根据自己实际业务需求
#cluster: #redies 集群配置
# maxRedirects: 3 # 最大集群连接数
# nodes:192.168.1.234:6380,192.168.1.235:6381
#sentinel: #哨兵配置
# master: redisMaster #监听的master名字
# nodes: 192.168.1.234:26379,192.168.1.235:26379,192.168.1.233:26379
@Data
@Configuration
@EnableCaching
@ConfigurationProperties(prefix = "spring.redis")
public class RedisConfig extends CachingConfigurerSupport {
private String host;
private String password;
private int port;
private int timeout;
private int database;
@Value("${spring.redis.lettuce.pool.min-idle}")
private int minIdle;
@Value("${spring.redis.lettuce.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.lettuce.pool.max-wait}")
private int maxWait;
@Value("${spring.redis.lettuce.pool.max-active}")
private int maxActive;
/**
* redis 序列化策略 ,通常情况下key值采用String序列化策略
* StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。StringRedisSerializer
* RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。JdkSerializationRedisSerializer
*
* @param lettuceConnectionFactory
* @return
*/
@Bean
@Primary
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(redisSerializer);
redisTemplate.setHashKeySerializer(redisSerializer);
GenericJackson2JsonRedisSerializer genericFastJsonRedisSerializer = getJackson2();
redisTemplate.setDefaultSerializer(genericFastJsonRedisSerializer);
redisTemplate.setValueSerializer(genericFastJsonRedisSerializer);
redisTemplate.setHashValueSerializer(genericFastJsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
private GenericJackson2JsonRedisSerializer getJackson2() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE);
objectMapper.setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE);
objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL,
JsonTypeInfo.As.PROPERTY);
SimpleFilterProvider filterProvider = new SimpleFilterProvider();
filterProvider.setDefaultFilter(SimpleBeanPropertyFilter.serializeAll());
objectMapper.setFilterProvider(filterProvider);
return new GenericJackson2JsonRedisSerializer(objectMapper);
}
/**
* SpringCache缓存管理器(SpringBoot 2.x),根据自身业务决定是否使用
* @param lettuceConnectionFactory
* @return
*/
@Bean
public CacheManager cacheManager(LettuceConnectionFactory lettuceConnectionFactory) {
GenericJackson2JsonRedisSerializer redisSerializer = getJackson2();
RedisSerializationContext.SerializationPair serializationPair
= RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer);
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration
.defaultCacheConfig().entryTtl(Duration.ofMinutes(30))//缓存失效时间
.serializeValuesWith(serializationPair);
return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(lettuceConnectionFactory))
.cacheDefaults(redisCacheConfiguration).build();
}
@Bean
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
return getJackson2();
}
/**
* boot2.x,将默认的jedis替换成了lettuce
*
* @return
*/
@Bean(destroyMethod = "destroy")
@Primary
public LettuceConnectionFactory lettuceConnectionFactory() {
GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
genericObjectPoolConfig.setMaxIdle(maxIdle);
genericObjectPoolConfig.setMinIdle(minIdle);
genericObjectPoolConfig.setMaxTotal(maxActive);
genericObjectPoolConfig.setMaxWaitMillis(maxWait);
LettuceConnectionFactory factory;
if (StrUtil.isNotEmpty(master)) {
//lettuce默认没有节点自动刷新机制,需要开启集群拓扑刷新和周期拓扑刷新(boot 2.3.x+ 可在yml配置)
ClusterTopologyRefreshOptions clusterTopologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
.enableAllAdaptiveRefreshTriggers() // 开启全部自适应刷新, 自适应刷新不开启,Redis集群变更时将会导致连接异常
.adaptiveRefreshTriggersTimeout(Duration.ofSeconds(5)) // 自适应刷新超时时间(默认30秒)
.enablePeriodicRefresh(Duration.ofSeconds(5)) // 开周期刷新, 默认关闭,开启后时间为60秒
.build();
ClusterClientOptions clientOptions = ClusterClientOptions.builder()
.topologyRefreshOptions(clusterTopologyRefreshOptions)
.build();
LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
.commandTimeout(Duration.ofMillis(timeout))
// .readFrom(ReadFrom.MASTER_PREFERRED) //优先从副本读取
.poolConfig(genericObjectPoolConfig)
.clientOptions(clientOptions) //自适应集群拓扑刷新和周期拓扑刷新
.build();
factory = new LettuceConnectionFactory(redisSentinelConfiguration(), clientConfig);
} else if (StrUtil.isNotEmpty(clusterNodes)) {
ClusterTopologyRefreshOptions clusterTopologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
.enableAllAdaptiveRefreshTriggers() // 开启全部自适应刷新, 自适应刷新不开启,Redis集群变更时将会导致连接异常
.adaptiveRefreshTriggersTimeout(Duration.ofSeconds(5)) // 自适应刷新超时时间(默认30秒)
.enablePeriodicRefresh(Duration.ofSeconds(5)) // 开周期刷新, 默认关闭,开启后时间为60秒
.build();
ClusterClientOptions clientOptions = ClusterClientOptions.builder()
.topologyRefreshOptions(clusterTopologyRefreshOptions)
.build();
LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
.commandTimeout(Duration.ofMillis(timeout))
.poolConfig(genericObjectPoolConfig)
.clientOptions(clientOptions) //自适应集群拓扑刷新和周期拓扑刷新
.build();
factory = new LettuceConnectionFactory(redisClusterConfiguration(), clientConfig);
} else {
LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
.commandTimeout(Duration.ofMillis(timeout))
.poolConfig(genericObjectPoolConfig)
.build();
factory = new LettuceConnectionFactory(redisStandaloneConfiguration(), clientConfig);
}
factory.setShareNativeConnection(false); //是否允许多个线程操作共用同一个缓存连接,默认true,false时每个操作都将开辟新的连接
factory.resetConnection(); // 重置底层共享连接, 在接下来的访问时初始化
return factory;
}
//集群模式
@Bean
public RedisClusterConfiguration redisClusterConfiguration() {
RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
redisClusterConfiguration.setMaxRedirects(maxRedirects);
redisClusterConfiguration.setPassword(password);
List<String> nodes = StringUtil.splitBySign(clusterNodes, ",");
Set<RedisNode> redisNodeSet = new HashSet<>();
nodes.forEach(url -> redisNodeSet.add(new RedisNode(url.split(":")[0].trim(), Integer.valueOf(url.split(":")[1]))));
redisClusterConfiguration.setClusterNodes(redisNodeSet);
return redisClusterConfiguration;
}
//哨兵模式
@Bean
public RedisSentinelConfiguration redisSentinelConfiguration() {
RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration();
RedisNode redisNode = new RedisNode(host, port);
redisNode.setName(master);
redisSentinelConfiguration.master(redisNode);
redisSentinelConfiguration.setDatabase(database);
redisSentinelConfiguration.setPassword(RedisPassword.of(password));
//配置redis的哨兵sentinel
Set<String> sentinelUrl = commaDelimitedListToSet(nodes);
Set<RedisNode> redisNodeSet = new HashSet<>();
sentinelUrl.forEach(url -> redisNodeSet.add(new RedisNode(url.split(":")[0].trim(), Integer.valueOf(url.split(":")[1]))));
redisSentinelConfiguration.setSentinels(redisNodeSet);
return redisSentinelConfiguration;
}
//单机模式
@Bean
public RedisStandaloneConfiguration redisStandaloneConfiguration() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setDatabase(database);
redisStandaloneConfiguration.setHostName(host);
redisStandaloneConfiguration.setPort(port);
redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
return redisStandaloneConfiguration;
}
/**
* Key生成策略
* @return
*/
@Bean
public KeyGenerator wiselyKeyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
};
}
}