SpringBoot2.1.X使用Redis连接池Lettuce踩坑
一、引言
近期项目频繁部署不同测试环境,在搭建运行环境与部署项目过程中踩到了不少Redis的坑。项目是基于SpringBoot2.1.12,SpringBoot2.1.X集成jar包Spring-data-redis-start 使用Lettuce作为Redis连接池。
- SpringBoot1.x默认采用Jedis作为redis客户端连接池。
- SpringBoot2.x,spring-data-redis 默认采用Lettuce作为redis客户端驱动连接池。
二、踩坑场景
运行环境Redis集群中某个master节点不稳定连接不上,导致SpringBoot应用连接Redis报错,报错连接timeout。
三、解决方案
基于Spring-data-redis重写RedisConnectionFactory Bean。需要设置“取消校验集群节点的成员关系”:.validateClusterNodeMembership(false)。
1、redis配置
spring: redis: cluster: nodes: - ${redis.host.cluster} #redis集群ip-port password: ${redis.password} timeout: 5000 #连接超时时间 lettuce: pool: max-active: 10 #连接池最大连接数 max-wait: -1 #连接池最大阻塞时间 max-idle: 5 #连接池中最大空闲连接 min-idle: 1 #连接池中最小空闲连接 redis: cluster: enabled: true
2、Config配置类
@Data @Component @ConditionalOnProperty(name = "redis.cluster.enabled", havingValue = "true", matchIfMissing = false) public class RedisConfig { @Autowired RedisProperties redisProperties; // 在构建LettuceConnectionFactory时,如果不使用内置的destroyMethod,可能会导致Redis连接早于其它Bean被销毁 @Bean(destroyMethod = "destroy") public RedisConnectionFactory newLettuceConnectionFactory() { // 配置用于开启自适应刷新和定时刷新。如自适应刷新不开启,Redis集群变更时将会导致连接异常 ClusterTopologyRefreshOptions clusterTopologyRefreshOptions = ClusterTopologyRefreshOptions.builder() .enablePeriodicRefresh(Duration.ofSeconds(60))// 开启周期刷新(默认60秒) .enableAdaptiveRefreshTriggers(RefreshTrigger.ASK_REDIRECT,RefreshTrigger.UNKNOWN_NODE)// 开启自适应刷新 .build(); ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder() .topologyRefreshOptions(clusterTopologyRefreshOptions)//拓扑刷新 .disconnectedBehavior(ClientOptions.DisconnectedBehavior.REJECT_COMMANDS) .autoReconnect(true) .socketOptions(SocketOptions.builder().keepAlive(true).build()) .validateClusterNodeMembership(false)// 取消校验集群节点的成员关系 .build(); LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder() .clientOptions(clusterClientOptions) .readFrom(ReadFrom.SLAVE_PREFERRED) .build(); return new LettuceConnectionFactory(getClusterConfiguration(), clientConfig); } private RedisClusterConfiguration getClusterConfiguration() { RedisProperties.Cluster clusterProperties = redisProperties.getCluster(); RedisClusterConfiguration config = new RedisClusterConfiguration(clusterProperties.getNodes()); if (clusterProperties.getMaxRedirects() != null) { config.setMaxRedirects(clusterProperties.getMaxRedirects()); } if (redisProperties.getPassword() != null) { config.setPassword(RedisPassword.of(redisProperties.getPassword())); } return config; } }
注意:
RedisClusterConfiguration getClusterConfiguration()需要设置Password,不然SpringBoot启动报认证错误:
“io.lettuce.core.RedisCommandExecutionException: NOAUTH Authentication required”。如下:
另外,lettuce-core jar包版本不能过低,避免部分配置项无法支持,以上配置为lettuce-core-5.18.RELEASE.jar。