JedisPool无法获得资源问题
线上碰到一个问题:
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
at redis.clients.util.Pool.getResource(Pool.java:22)
线上会相隔不定时的天数后出现一次JedisPool种getresouce拿不到resource的情况。中间陆陆续续上过很多次线,然后废了很大劲努力排除掉了业务可能和多次上线的代码问题。业务数据量即便是在测试环境种建造了更多,也不会导致那种情况的出现。而业务代码测试环境和线上相同,后来在测试环境压测的压力和线上差不多的情况下,也不会重现这个问题。
后来就有一种束手无策的感觉了,最后只能推论是当时应用集群到Redis集群的网络出了问题了,但是由于种种原因一直没有在集群间添加网络状态的监控,也就只能是猜测了,但是又没办法重现。后来偷偷在线上的一台服务器上面添加了ping的监控,很简单:ping -i 1 192.168.134.155 > pinglog_{`date +%Y-%m-%d`}.log &,该命令的效果比较简单,就是每隔1sping一次目标服务器,然后打印到按天分开的日志里面。然而这种事情不再出现我们酒没办法验证推论,领导又催的非常紧,没办法还是需要验证出来啊。
开始的时候,根据代码来找原因,代码里面从jedispool种获得jedis资源实例的代码是使用了java7里面的try-with-resouce的写法,也就是用完之后,于是就怀疑是不是这种写法,在try块里面有了其他异常会导致resouce无法正常关闭,导致某个Jedis实例用完后没有还给JedisPool,导致资源不足?
public class JedisTest {private static final JedisPool jedisPool;static {JedisPoolConfig config = new JedisPoolConfig();config.setMaxIdle(20);config.setMaxTotal(40);config.setMinIdle(10);jedisPool = new JedisPool(config, "127.0.0.1", 8279, 1000);}public static void main(String[] args) {try(Jedis jedis = jedisPool.getResource()){throw new Exception("~");}catch (Exception e){//do nothing }} }
后来其实在JedisPool里面的断点很容易就可以看到java7 并没有错误,多心了。
于是,那还是回归主题,其实只要认真分析,不会又那么困难的问题出现:
其实getresouce报错有两种可能:
1、本身有错误---排除,首先如果这个方法有错误,那么之前应该会一直出现,或者其他人也早该把开源包的错误爆出,排除这种可能;
2、就是在规定时间内没取到资源。
刚才我们看maxtotal里面定义了池子最大就40个,如果真的40个都在用,并且在超时的100ms内没人return resouce,那报错也正常。
也就是说,我们出现了40个全部被用到,并且在超时的100ms内没有任何资源还给JedisPool。
后来恰好,在打印的jstack的信息种发现了大量的time_waiting状态的线程在等待从Jedispool.getResouce().
那么什么情况下会导致这个情况出现?
假设现在并发来了41个请求,然后其中40个正常的进行,但是第41没拿到资源,于是等待规定的超时时间,但是这会从应用到Redis集群间网络出现抖动,暂时不通,会导致40个请求种的里面的jedis的get或者set操作变慢甚至超时。
我们设想一种情况:从jedisPool里面拿资源的超时时间是100ms,程序里面进行get或者set资源的是200ms超时,那么就有可能出现这种情况。
事实证明我们的配置确实是jedis里面去get或者set一个key的时候,超时时间是200ms,那也就是说,如果网络发生了抖动,那就会在并发的情况下迅速耗光资源池,然后超时后报错才还回去,但是那个时间早就发生了getResouce的错误。
Bingo,其实很简单的原因,那就是没有正确的理解两个超时时间之间的关系。
我们可以简单测试一下:
public static void main(String[] args) {ExecutorService service = Executors.newFixedThreadPool(20);for(int i = 0;i < 20 ;i ++){service.execute(new Runnable() {@Overridepublic void run() {try(Jedis jedis = jedisPool.getResource()) {Thread.sleep(200L);} catch (InterruptedException e) {System.out.println(e);}}});}}
由于本地环境问题,只是示例代码,就不执行了。其实很容易就还原了问题出来。
后面只要调小jedis的get和set方法的超时时间,同时也尽量小的使用getresource的超时时间(这里为什么不加大,因为在高并发的情况下会迅速耗光线程数量,jstack里面甚至出现了500个线程有450个是time_waiting的状态,这可不是我们想要的结果)。
然后在服务器之间添加监控和警报,及时报警进行网络的修复。
转载于:https://www.cnblogs.com/congsg2016/p/5328976.html
JedisPool无法获得资源问题相关推荐
- JedisPool资源池优化
本文作者:carlosfu 原文链接:https://yq.aliyun.com/articles/236383 摘要: 合理的JedisPool资源池参数设置能为业务使用Redis保驾护航,本文将对 ...
- Hrm-人力资源系统开发笔记05
1.无限极树优化 1.1.为什么要优化 每次都要从数据库查询一次. 使用的地方&问题: 1)后台管理 课程类型列表要使用 课程类型树,在后面添加课程时会反复使用.通过下拉选择对应的类型 就算每 ...
- webapi控制器怎么接收json_一个秒杀系统的登录系统到底是怎么工作的
本部分内容 这部分主要是从客户端输入网址到登录成功 进入主页 一般来说,输入的网址会被controller层拦截,但是如果在只输入了主机,没有输入其他的内容那么就会默认载入template中的inde ...
- 搭建一个完整的微服务项目
一.项目技术架构 1.技术栈 前台技术 Node.js.Npm.Vue.js.WebPack.Vue Cli.Element UI 后台架构 微服务架构:按照功能拆分N多个服务,每个服务可以独立技术选 ...
- 基于Redis实现简单的分布式锁
在分布式场景下,有很多种情况都需要实现最终一致性.在设计远程上下文的领域事件的时候,为了保证最终一致性,在通过领域事件进行通讯的方式中,可以共享存储(领域模型和消息的持久化数据源),或者做全局XA事务 ...
- Java异常 | JedisException: Could not get a resource from the pool
1. 异常现象 20190429 16:27:58,200 | ERROR | (RedisClient.java:262)RedisClient:262 - jedisInfo ... NumAct ...
- HRM人力资源系统-Day05
课程类型的优化 无限极树的优化 方案一:发送一条SQL 将所以数据都查询出来 然后在通过循环将子级节点放入到父级节点中 代码实现: //循环方案-一条sql自己组织关系 private List< ...
- hrm项目-day02
文章目录 一.课程分类树状展示 1.前端(略过不用管) 2.后台课程服务编写查询方法 1.CourseTypeController编写查询方法 2.CourseTypeService实现方法 3.实现 ...
- Springcloud HRM微服务项目(二)
文章目录 课程类型数据查询 1.如何查询数据 2.如何封装数据 3.配置跨域 给课程分类做缓存 1.简介 2.搭建基础服务 3.集成redis 1.导包 2.工具类 3.测试工具类 4. redis服 ...
最新文章
- 数据科学中的6个基本算法,掌握它们要学习哪些知识
- windows下快速启动或关闭系统服务方法
- 深入async/await知多少
- axios安装_一起学Vue:访问API(axios)
- 高职计算机等级考试试题,高职院校计算机等级考试的教学与思考
- visual studio Code配置C++环境:
- 一个奇怪的问题:tomcat 栈溢出 StackOverflowError错误
- EJB3.0框架实例----区分有状态bean和无状态bean
- 安装mysql第三步卡死_Mysql 安装服务无法启动解决方案与使用的一般使用指令
- 使用Spring Data JPA作为持久层框架
- iocomp iPlot使用说明13 Limits绘图界限
- 公众号900篇文章分类和索引
- Android 关于图片的压缩
- js写的 几款时间轴
- 冰峰王座完整的语音英文+中文解释!(修订版)
- Lua 报错 PANIC: unprotected error in call to Lua API (no calling environment) 解决办法
- MAC打印出现Filter failed
- 10005 内联函数
- Linux_进程控制(创建进程,等待进程,进程终止)
- javaee.jar与servlet-api.jar