记一次生产环境获取不到redis连接问题排查

最近线上环境总是不稳定,用着用着就会出现获取不到redis连接的情况,查看redis服务器端配置,发现连接数不是很多,那么为什么又会出现如此情况呢?

首先查看redis服务端的配置
## 通过redis-cli连接到redis服务器
redis-cli -h 127.0.0.1 -p 6379 -a 密码
##获取客户端信息
info clients
## 输出信息,可以查看客户端连接数
connected_clients:19
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0
## 查看服务端空闲时间(空闲时间超过这个时间服务端会断开连接,默认服务端是不会主动断开连接的)
config timeout
## 查看服务端总连接数
config maxclients
发现服务端各方面连接数都很正常,那么为什么客户端又经常报获取不到连接的异常呢

回顾一下项目,项目用的技术栈主要 springmvc + mybatis + spring cache + shiro ,会大量用到redis的地方一个是shiro的sesion操作,另一个就是spring cache的cache操作

在本地先把redis的最大,最小空闲连接数设为20,总连接数设为50

大量操作会通过spring cache处理的接口,查看redis服务端连接,发现连接数很快会占满到最大的连接数,然后没过一会客户端开始报获取不到连接错误

思考,是本地连接没有及时释放的原因吗?OK,调整连接池的配置参数
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        //总连接数 50
        jedisPoolConfig.setMaxTotal(maxTotal);
        //最大等待时间(毫秒)
        jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
        //最大空闲连接数
        jedisPoolConfig.setMaxIdle(maxIdle);
        //最小空闲连接数
        jedisPoolConfig.setMinIdle(minIdle);
        //释放连接的扫描间隔(毫秒)
        jedisPoolConfig.setTimeBetweenEvictionRunsMillis(10);
        //连接空闲多久后释放(毫秒),
        jedisPoolConfig.setSoftMinEvictableIdleTimeMillis(100);
        //拿到连接的时候是否进行校验操作
        jedisPoolConfig.setTestOnBorrow(true);
        //连接归还池进行校验
        jedisPoolConfig.setTestOnReturn(true);
        //自动测试池中的空闲连接都是可用
        jedisPoolConfig.setTestWhileIdle(true);
        //每次释放连接的最大数目
        jedisPoolConfig.setNumTestsPerEvictionRun(10);
对连接池做以上配置,再进行测试,发现同样的问题还是存在,思考,进行了上述配置后为什么连接还是没有断开?难道连接泄露了?考虑到本项目是通过jedis来操作redis的,jedis获取redis连接,用完后需要调用close来归还连接,难道是没有归还连接?
查看所有调用jedis的地方,发现操作session的时候拿了连接之后并没有归还,ok,修复该问题,再进行压测,一切正常。

主要提几点

  • 如果引用了spring cache 和 shiro 框架,又是用redis来存储,那么操作频次是非常高的,一定要注意连接的问题
  • 使用jedis操作redis一定要注意用完后调用close方法,不然连接是得不到及时归还的
  • 对于大并发的情况下,redis连接的空闲存活期一定要设置的短一点,以便于连接及时释放
  • 对于并发量比较大,同时多个项目共用同一redis服务器的情况下,要注意服务器端 timeout参数的设置

你可能感兴趣的:(redis)