记录一次Redis链接池超MaxConnection&链接不释放问题

前言

新系统构建时需要分布式Session&Cache支撑,为子系统之间提供服务和数据共享。测试环境为单机搭建三主三从的集群,一次测试突然报错Connection Rest (链接重置了)。后续排查发现是Redis吃了3500多个链接!发现redis链接不释放并且一直在Ping!

链接不释放

问题分析

很明显就是没有回收链接!并且一直在ping导致jedis认为链接是有效无法释放。

解决思路

1. 调整JedisPool大小

 因为之前压测链接不够配置成600现调整为120的最大链接(没看懂为什么我设置的600 redis链接可以到3500多,先解决链接不释放问题)

2. 控制最大空闲链接

 之前设置是150个现设置成50个

3.打开空闲链接释放检查

 设置空闲链接检查时间为5S检查一次

结果是链接还是不释放并且链接总数340多!

代码如下:

 @Bean("jedisPoolConfig")
    public JedisPoolConfig jedisPoolConfig(){
        JedisPoolConfig jpc = new JedisPoolConfig() ;
        jpc.setMaxIdle(50);
        jpc.setMinIdle(20);
        jpc.setMaxTotal(120);
        jpc.setNumTestsPerEvictionRun(50);
        jpc.setTestOnBorrow(true);
        jpc.setTestOnReturn(false);
        jpc.setBlockWhenExhausted(true);
        jpc.setTimeBetweenEvictionRunsMillis(5000);
        jpc.setTestWhileIdle(true);
        jpc.setMaxWaitMillis(15000);
        return jpc ;
    }
    
    @Bean("jedisConnectionFactory")
    public JedisConnectionFactory jcf(@Qualifier("jedisPoolConfig") JedisPoolConfig jpc){
        RedisClusterConfiguration rcc = new RedisClusterConfiguration(Arrays.asList("redis链接信息"));
        rcc.setMaxRedirects(6);
        rcc.setPassword(RedisPassword.of("?????"));
        return new JedisConnectionFactory(rcc,jpc) ;
    }

到这来感觉有点无从下手了:驱逐政策如下

 1. 设置了最大空闲链接  : pc.setMaxIdle(50);

 2. 设置了清理空闲链接的配置  :jpc.setTimeBetweenEvictionRunsMillis(5000); jpc.setTestWhileIdle(true);

由上可知链接的创建&驱逐&使用全部是由Pool进行控制的。

于是乎我开始怀疑Jedis是不是检查空闲的代码有问题打开源代码如下:

如图可知 需要链接是通的并且可Ping通那Pool认为这个链接就是有效的!这逻辑看上去并没有问题!因此可知驱逐策略肯定受Ping和链接超时影响!由此可知驱逐策略就是在检查链接是否通讯正常&&ping(能解释一开始为什么大量链接在Ping)能否成功。使用驱逐策略必须破坏某个条件才可以触发。

新思路

1. redis服务器屏蔽Ping ---不推荐影响正常的存活检查策略

2. 想办法设置TCP链接时长 --- 这个看一下redis官网配置文件详解肯定有相关配置 

查询Redis配置文件示例可知以下配置可达上述效果

 timeout等待命令时间单位秒
tcp-keepaliveTCP保持。。。

                        

打开redis配置文件发现timeout是默认值0永不超时!由此可知是因为链接没有超时时间,导致jedis客户端每一个TimeBetweenEvictionRunsMillis周期内的Ping命令生效。使JedisPool驱逐政策无法触发。所有我们只需要配置的驱逐时间稍大于redis服务器超时时间既可。到此链接不释放问题已解决。

redis链接数超过JedisPool最大链接数

问题分析

JedisPool代码应该不用怀疑,这些框架自带池不会出这种很明显的“BUG”。开始看源码!

通过链接不释放的问题可知链接是由JedisConnectionFactory 进行维护。开始分析JedisConnectionFactory源码。

源码分析

有继承Sping的生命周期钩子:

Bena对象初始化以后创建RedisCluster

初始化redis的KeySlot(创建Key和redis实例的映射:说明我这个Key路由到哪一个Redis上面)

找到Pool相关配置

发现核心创建Pool的代码

结论

综上所述我们配置的JedisPoolConfig并不是针对整个RedisCluster共享的池配置,而是针对每一个redis实例进行的描述。所以我发现maxConnect=120实际redis使用链接是340多是在正常范围内的!(ps: 340/6=56.66....是接近我们配置maxidle的而且稳定在这个范围)。

  • 19
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值