记一次线上环境 redis偶尔连接超时报错 解决

记一次线上环境 redis偶尔连接超时报错 解决

 

贴出本地控制台日志

 

 

 

说实话,很痛苦,跟进很久了,一直认为的jvm程序所使用的配置的连接池框架问题

因为程序为 springboot 2 spring 5 ;那么默认连接池为 lettuce

起初认为是原有的jedis 转换到 lettuce存在的各种bug问题,可能没配置好;

 

网上也寻找了相关的文章,发现大多数人的解决方案,就是在springboot的自动注入的配置文件中,配置不对,说spring.redis.timeout配置为0,导致不允许超时,那么就会抛出该异常;

所以只需要将其改为合理的范围即可,比如10s,那么本人也试过了,发现不顶用。

此处贴出配置文件(注:rediss不是写错,是故意不使用自动配置注入的):

然后就是连接池的问题了,本人尝试使用自定义注入连接池使用,不使用自动注入(此处怀疑是自动注入问题)结果也发现不行,

那么再怀疑是配置项不对,例如连接池的最小空闲链接、最大空闲链接数不合理,那么我本地在尝试调整的时候,本地模拟运行一段时间,发现还是会时不时抛出超时问题;

此处贴出本人的自定义注入配置文件(一个lettuce连接工厂)

/**
 * @description: LettuceConfiguration
 * @author: Wang Ji
 * @create: 2021/01/22 21:24
 */
@Slf4j
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class LettuceConfig {
​
    @Value("${spring.rediss.database}")
    private int database = 0;
​
    @Value("${spring.rediss.host}")
    private String host;
​
    @Value("${spring.rediss.port}")
    private int port;
​
    @Value("${spring.rediss.password}")
    private String password = null;
​
    @Value("${spring.rediss.timeout}")
    private int timeout = 5000;
​
    @Value("${spring.rediss.lettuce.pool.max-idle}")
    private int maxIdle = 8;
​
    @Value("${spring.rediss.lettuce.pool.min-idle}")
    private int minIdle = 0;
​
    @Value("${spring.rediss.lettuce.pool.max-active}")
    private int maxActive = 8;
​
    @Value("${spring.rediss.lettuce.pool.max-wait}")
    private long maxWait;
​
    /**
     * lettuce 连接工厂
     *
     * @param genericObjectPoolConfig
     * @return
     */
    @Bean("redisConnectionFactory")
    public RedisConnectionFactory redisConnectionFactory(@Qualifier("genericObjectPoolConfig") GenericObjectPoolConfig<?> genericObjectPoolConfig) {
        // 单机版配置
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setDatabase(database);
        redisStandaloneConfiguration.setHostName(host);
        redisStandaloneConfiguration.setPort(port);
        redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
​
        // 集群版配置
//        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
//        String[] serverArray = clusterNodes.split(",");
//        Set<RedisNode> nodes = new HashSet<RedisNode>();
//        for (String ipPort : serverArray) {
//            String[] ipAndPort = ipPort.split(":");
//            nodes.add(new RedisNode(ipAndPort[0].trim(), Integer.valueOf(ipAndPort[1])));
//        }
//        redisClusterConfiguration.setPassword(RedisPassword.of(password));
//        redisClusterConfiguration.setClusterNodes(nodes);
//        redisClusterConfiguration.setMaxRedirects(maxRedirects);
​
        LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
                .commandTimeout(Duration.ofMillis(timeout))
                .poolConfig(genericObjectPoolConfig)
                .build();
        RedisConnectionFactory redisConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration, clientConfig);
        if (ConnectionUtils.isLettuce(redisConnectionFactory)) {
            log.warn("// RedisConnectionFactory is Lettuce");
        } else if (ConnectionUtils.isJedis(redisConnectionFactory)) {
            log.warn("// RedisConnectionFactory is Jedis");
        }
​
        return redisConnectionFactory;
    }
​
​
    /**
     * GenericObjectPoolConfig 连接池配置
     *
     * @return
     */
    @Bean("genericObjectPoolConfig")
    public GenericObjectPoolConfig<?> genericObjectPoolConfig() {
        GenericObjectPoolConfig<?> genericObjectPoolConfig = new GenericObjectPoolConfig<>();
        genericObjectPoolConfig.setMaxIdle(maxIdle);
        genericObjectPoolConfig.setMinIdle(minIdle);
        genericObjectPoolConfig.setMaxTotal(maxActive);
        genericObjectPoolConfig.setMaxWaitMillis(maxWait);
        return genericObjectPoolConfig;
    }
}

 

然后在一篇文章中也看到,可能存在一个这样的问题,redis在长时间空闲状态,会自动重启?

本人没验证过,猜测可能是某种垃圾回收策略,内存碎片化整理。有兴趣的同学可以去研究一下。

 

那么本人再次怀疑,可能就是redis本身的config配置不对,因为笔者对于redis的自己的服务器上的部署都是全部自定义过的,也就是说,很多配置,都对其进行了适合自己项目的配置,比如回收策略,数据库数量,最大连接数量,等等等,那么按常理来说,redis的本身服务上也会有一个超时配置。

一找,果不其然有个超时配置;

但是这个配置是:客户端闲置N秒后关闭连接(0禁用)

按道理来说,0应该是禁用了主动关闭连接的配置

这里,我将尝试改为300s 后 超时

那么并且修改配置文件中的 多少秒检测一次空闲状态

 

修改这样,然后我后面再尝试运行一段时间,看看结果怎样

 

注意,此调试方案建议不要直接用于生产环境

因为每个公司服务的策略都不一样,毕竟脱离业务的架构方案都是耍流氓,建议可以以拓展知识面的方式阅读本文章。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值