import io.lettuce.core.ClientOptions; import io.lettuce.core.cluster.ClusterClientOptions; import io.lettuce.core.cluster.ClusterTopologyRefreshOptions; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; import org.springframework.context.annotation.Bean; import org.springframework.data.redis.connection.RedisClusterConfiguration; import org.springframework.data.redis.connection.RedisNode; import org.springframework.data.redis.connection.RedisPassword; import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; import org.springframework.stereotype.Component; import java.time.Duration; import java.util.HashSet; import java.util.List; import java.util.Set; /** * @author : 007 * @version : 2.0 * @date : 2020/7/27 10:19 */ @Component public class RedisConfig { @Autowired private RedisProperties redisProperties; public GenericObjectPoolConfig<?> genericObjectPoolConfig(RedisProperties.Pool properties) { GenericObjectPoolConfig<?> config = new GenericObjectPoolConfig<>(); config.setMaxTotal(properties.getMaxActive()); config.setMaxIdle(properties.getMaxIdle()); config.setMinIdle(properties.getMinIdle()); if (properties.getTimeBetweenEvictionRuns() != null) { config.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRuns().toMillis()); } if (properties.getMaxWait() != null) { config.setMaxWaitMillis(properties.getMaxWait().toMillis()); } return config; } @Bean(destroyMethod = "destroy") public LettuceConnectionFactory lettuceConnectionFactory() { //开启 自适应集群拓扑刷新和周期拓扑刷新 ClusterTopologyRefreshOptions clusterTopologyRefreshOptions = ClusterTopologyRefreshOptions.builder() // 开启全部自适应刷新 .enableAllAdaptiveRefreshTriggers() // 开启自适应刷新,自适应刷新不开启,Redis集群变更时将会导致连接异常 // 开启自适应刷新 //.enableAdaptiveRefreshTrigger() // 自适应刷新超时时间(默认30秒) .adaptiveRefreshTriggersTimeout(Duration.ofSeconds(30)) //默认关闭开启后时间为30秒 // 开周期刷新 .enablePeriodicRefresh(Duration.ofSeconds(20)) // 默认关闭开启后时间为60秒 ClusterTopologyRefreshOptions.DEFAULT_REFRESH_PERIOD 60 .enablePeriodicRefresh(Duration.ofSeconds(2)) = .enablePeriodicRefresh().refreshPeriod(Duration.ofSeconds(2)) .build(); // https://github.com/lettuce-io/lettuce-core/wiki/Client-Options ClientOptions clientOptions = ClusterClientOptions.builder() .topologyRefreshOptions(clusterTopologyRefreshOptions) .build(); LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder() .poolConfig(genericObjectPoolConfig(redisProperties.getJedis().getPool())) //.readFrom(ReadFrom.MASTER_PREFERRED) .clientOptions(clientOptions) .commandTimeout(redisProperties.getTimeout()) //默认RedisURI.DEFAULT_TIMEOUT 60 .build(); List<String> clusterNodes = redisProperties.getCluster().getNodes(); Set<RedisNode> nodes = new HashSet<RedisNode>(); clusterNodes.forEach(address -> nodes.add(new RedisNode(address.split(":")[0].trim(), Integer.valueOf(address.split(":")[1])))); RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration(); clusterConfiguration.setClusterNodes(nodes); clusterConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword())); clusterConfiguration.setMaxRedirects(redisProperties.getCluster().getMaxRedirects()); LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(clusterConfiguration, clientConfig); // lettuceConnectionFactory.setShareNativeConnection(false); //是否允许多个线程操作共用同一个缓存连接,默认true,false时每个操作都将开辟新的连接 // lettuceConnectionFactory.resetConnection(); // 重置底层共享连接, 在接下来的访问时初始化 return lettuceConnectionFactory; } }
public LettuceConnectionFactory redisConnectionFactory(ClientResources clientResources) { // redis单节点 if (null == redisProperties.getCluster() || null == redisProperties.getCluster().getNodes()) { RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(redisProperties.getHost(), redisProperties.getPort()); configuration.setPassword(redisProperties.getPassword()); return new LettuceConnectionFactory(configuration); } ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder() // //按照周期刷新拓扑 .enablePeriodicRefresh(Duration.ofSeconds(30)) //根据事件刷新拓扑 .enableAllAdaptiveRefreshTriggers() .build(); ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder() //redis命令超时时间,超时后才会使用新的拓扑信息重新建立连接 .timeoutOptions(TimeoutOptions.enabled(Duration.ofSeconds(10))) .topologyRefreshOptions(topologyRefreshOptions) .build(); LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder() .clientResources(clientResources) .clientOptions(clusterClientOptions) .build(); RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(redisProperties.getCluster().getNodes()); if (redisProperties.getCluster().getMaxRedirects() != null) { clusterConfig.setMaxRedirects(redisProperties.getCluster().getMaxRedirects()); } clusterConfig.setPassword(RedisPassword.of(redisProperties.getPassword())); return new LettuceConnectionFactory(clusterConfig, clientConfiguration); }
方法二
改用jedis方式连接redis,使用jedis客户端的服务可以在主从切换后15秒恢复
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <exclusions> <exclusion> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency>
注意配置文件把lettuce.pool换成jedis.pool
- lettuce 配置信息
spring.redis.lettuce.pool.max-active=10 spring.redis.lettuce.pool.max-idle=10 spring.redis.lettuce.pool.max-wait=10 spring.redis.lettuce.pool.min-idle=5 spring.redis.lettuce.shutdown-timeout=1S
- jedis 配置信息
spring.redis.jedis.pool.max-active=10 spring.redis.jedis.pool.max-idle=10 spring.redis.jedis.pool.max-wait=10 spring.redis.jedis.pool.min-idle=5
spring: redis: password: xxx host: 172.16.0.x port: 6579 timeout: 5000 jedis: pool: #最大连接数据库连接数,设 0 为没有限制 max-active: 8 #最大等待连接中的数量,设 0 为没有限制 max-idle: 8 #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。 max-wait: -1ms #最小等待连接中的数量,设 0 为没有限制 min-idle: 0 #lettuce: #pool: #max-active: ${redis.config.maxTotal:1024} #max-idle: ${redis.config.maxIdle:50} #min-idle: ${redis.config.minIdle:1} #max-wait: ${redis.config.maxWaitMillis:5000}
springboot 2.3
配置属性
spring.redis.lettuce.cluster.refresh.adaptive= true spring.redis.lettuce.cluster.refresh.period=30000
spring: redis: lettuce: cluster: refresh: adaptive: true period: 30000 # 30秒自动刷新一次