redis 问题记录
问题1:
问题描述:今天在对环境进行验证时,看到系统中经常报类似“So far, the system has appeared 2270423 times JedisConnectionException”这样的错误。
问题分析:报错原因是系统与redis之间的连接问题。经查是由于当前环境所部署系统的redis开关都打开着的,但是环境中却并未配置redis服务器。
由此,更进一步了解一下redis连接池相关的内容。
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resourc
使用redis作为缓存工具,很容易出现从redis连接池中得不到连接的问题。而使用redis连接池获取连接的时候,往往是在高并发情形下,出现如题所示的问题。本人一般从如下几个方面排查,经验之谈~ 1)首先判断redis连接参数是否配置正确?很有可能,之前一直能取,但现在突然出现异常,很有可能是redis的服务器down掉了,或者redis的连接条件被更改; 2)网络权限更改:做过项目就很容易知道,每种环境的权限是不同的,很有可能你项目所在的网段连接redis的权限被更改,导致之前一直可以获取redis连接,但现在却无法获取。 3)查代码:一般而言,从redis里面获取连接取数据,完毕之后应该立即归还到池中。应该注意的是,一般都会用典型的try{} catch{} finally{}结构包围,在finally{}中释放连接(这样可以确保无论是否发生异常,redis的连接都能及时被归还到连接池中); 4)归还redis连接必须要注意的一点,如:
//从连接池获取连接
Jedis jedis = pool.getResource();
try{
}catch(Exception e) {
e.printStackTrace();
}finally{
//归还连接到redis池中
poo.returnResource();
}
这段代码看起来很满足3)的规范,在finally里归还了连接。但!有一个隐藏的容错性考虑,当Jedis jedis = pool.getResource();这段代码发生异常时,finally的代码是不会被执行的。我可以模拟一下,
String str = null; system.out.println(str.length());//模拟异常 try{ System.out.println("模拟从redis取数据"); }catch(Exception e) { e.printStackTrace(); }finally{ System.out.println("连接释放。。。"); }
运行报异常,finally里面的代码不会被执行。所以,应该改成这样:
//从连接池获取连接
Jedis jedis = null;
try{
jedis = pool.getResource();
}catch(Exception e) {
e.printStackTrace();
}finally{
//归还连接到redis池中
poo.returnResource();
}
当然,这是由于try catch finally的机制决定,但很容易被忽视~
再不济的话,提高redis池连接个数和最大空闲数等参数……
问题2:
问题描述:测试redis服务时,TPS到达一定值后,无法提升了。需要调优。
问题原因:
并发时,redis服务器软中断(top 命令cpu的si值)很高。redis是单进程,可能是网卡中断与redis使用的进程CPU争用CPU所致。把两个分隔,redis进程绑定到其他CPU核上后,tps提高了30%。---网卡一般用CPU0
网卡软中断指单个网卡队列只能使用一个CPU,高并发下网卡数据交互都集中在同一个CPU,导致无法充分利用多核CPU的情况。网卡软中断瓶颈一般出现在网络高流量吞吐的场景下。
解决方法:
redis的master单独绑定一个CPU核数,避免和网卡中断互用CPU。由运维手动指定CPU(taskset命令)或开发人员绑定进程在单独的CPU上
注意:绑定CPU这个正常没有问题,但是有例外情况。当父进程创建子进程进行RDB/AOF重写时,如果做了CPU绑定,会与父进程共享一个CPU。子进程重写时对单核CPU使用率通常在90%以上,父进程与子进程将产生激烈CPU竞争,极大影响redis的稳定性。因此对于开启了持久化或参与复制的主节点,不建议绑定CPU。
参考资料:

浙公网安备 33010602011771号