jedis连接池参数minEvictableIdleTimeMillis和softMinEvictableIdleTimeMillis探索
我们通常在使用JedisPoolConfig进行连接池配置的时候,minEvictableIdleTimeMillis和softMinEvictableIdleTimeMillis这两个参数经常会不懂其含义,
查各种资料也没有非常明确的说到底该如何设置,即使知道如何设置,也不知道其原理,只知道这两个参数是和逐出线程有关的。下面根据源码进行探索。
我们通常是通过JedisPool构造线程池,追溯其父类的创建过程,发现Pool<T>这个泛型类的构造方法调用过程如下:
public Pool(GenericObjectPoolConfig poolConfig, PooledObjectFactory<T> factory) {
this.initPool(poolConfig, factory);
}
public void initPool(GenericObjectPoolConfig poolConfig, PooledObjectFactory<T> factory) {
if(this.internalPool != null) {
try {
this.closeInternalPool();
} catch (Exception var4) {
;
}
}
this.internalPool = new GenericObjectPool(factory, poolConfig);
}
发现其创建了一个GenericObjectPool对象,构造方法如下:
public GenericObjectPool(PooledObjectFactory<T> factory, GenericObjectPoolConfig config) {
super(config, "org.apache.commons.pool2:type=GenericObjectPool,name=", config.getJmxNamePrefix());
this.factoryType = null;
this.maxIdle = 8;
this.minIdle = 0;
this.allObjects = new ConcurrentHashMap();
this.createCount = new AtomicLong(0L);
this.abandonedConfig = null;
if(factory == null) {
this.jmxUnregister();
throw new IllegalArgumentException("factory may not be null");
} else {
this.factory = factory;
this.idleObjects = new LinkedBlockingDeque(config.getFairness());
this.setConfig(config);
this.startEvictor(this.getTimeBetweenEvictionRunsMillis());
}
}
其中this.startEvictor(this.getTimeBetweenEvictionRunsMillis());方法的调用,正是开启逐出线程运行的作用,
我们可以发现,源码通过周期性的调度逐出任务(timeBetweenEvictionRunsMillis大于0时),将空闲的连接逐出线程池。
final void startEvictor(long delay) {
Object var3 = this.evictionLock;
synchronized(this.evictionLock) {
if(null != this.evictor) {
EvictionTimer.cancel(this.evictor);
this.evictor = null;
this.evictionIterator = null;
}
if(delay > 0L) {
this.evictor = new BaseGenericObjectPool.Evictor();
EvictionTimer.schedule(this.evictor, delay, delay);
}
}
}
下面将是我们今天研究的重点,this.evictor。
逐出有逐出策略,如果不配置则采用默认的逐出策略DefaultEvictionPolicy,其中的evict方法返回true时才执行逐出的操作
public class DefaultEvictionPolicy<T> implements EvictionPolicy<T> {
public DefaultEvictionPolicy() {
}
public boolean evict(EvictionConfig config, PooledObject<T> underTest, int idleCount) {
return config.getIdleSoftEvictTime() < underTest.getIdleTimeMillis() && config.getMinIdle() < idleCount || config.getIdleEvictTime() < underTest.getIdleTimeMillis();
}
}
真正的逐出方法执行的是以下内容
public void evict() throws Exception {
this.assertOpen();
if(this.idleObjects.size() > 0) {
PooledObject<T> underTest = null;
EvictionPolicy<T> evictionPolicy = this.getEvictionPolicy();
Object var3 = this.evictionLock;
synchronized(this.evictionLock) {
EvictionConfig evictionConfig = new EvictionConfig(this.getMinEvictableIdleTimeMillis(), this.getSoftMinEvictableIdleTimeMillis(), this.getMinIdle());
boolean testWhileIdle = this.getTestWhileIdle();
int i = 0;
int m = this.getNumTests();
while(true) {
if(i >= m) {
break;
}
if(this.evictionIterator == null || !this.evictionIterator.hasNext()) {
this.evictionIterator = new EvictionIterator(this, this.idleObjects);
}
if(!this.evictionIterator.hasNext()) {
return;
}
label81: {
try {
underTest = this.evictionIterator.next();
} catch (NoSuchElementException var15) {
--i;
this.evictionIterator = null;
break label81;
}
if(!underTest.startEvictionTest()) {
--i;
} else {
boolean evict;
try {
evict = evictionPolicy.evict(evictionConfig, underTest, this.idleObjects.size());
} catch (Throwable var14) {
PoolUtils.checkRethrow(var14);
this.swallowException(new Exception(var14));
evict = false;
}
if(evict) {
this.destroy(underTest);
this.destroyedByEvictorCount.incrementAndGet();
} else {
if(testWhileIdle) {
boolean active = false;
try {
this.factory.activateObject(underTest);
active = true;
} catch (Exception var13) {
this.destroy(underTest);
this.destroyedByEvictorCount.incrementAndGet();
}
if(active) {
if(!this.factory.validateObject(underTest)) {
this.destroy(underTest);
this.destroyedByEvictorCount.incrementAndGet();
} else {
try {
this.factory.passivateObject(underTest);
} catch (Exception var12) {
this.destroy(underTest);
this.destroyedByEvictorCount.incrementAndGet();
}
}
}
}
if(!underTest.endEvictionTest(this.idleObjects)) {
;
}
}
}
}
++i;
}
}
}
AbandonedConfig ac = this.abandonedConfig;
if(ac != null && ac.getRemoveAbandonedOnMaintenance()) {
this.removeAbandoned(ac);
}
}
我们重点看两行代码,第8行是创建了逐出配置,根据你配置的minEvictableIdleTimeMillis和softMinEvictableIdleTimeMillis,如果存在负数,则设为long类型的最大值。
public EvictionConfig(long poolIdleEvictTime, long poolIdleSoftEvictTime, int minIdle) {
if(poolIdleEvictTime > 0L) {
this.idleEvictTime = poolIdleEvictTime;
} else {
this.idleEvictTime = 9223372036854775807L;
}
if(poolIdleSoftEvictTime > 0L) {
this.idleSoftEvictTime = poolIdleSoftEvictTime;
} else {
this.idleSoftEvictTime = 9223372036854775807L;
}
this.minIdle = minIdle;
}
再看第40行代码,再结合DefaultEvictionPolicy的evict方法,我们可以看到,真正的逐出依据是:
1.连接空闲时间大于softMinEvictableIdleTimeMillis并且当前连接池的空闲连接数大于最小空闲连接数minIdle;
2.连接空闲时间大于minEvictableIdleTimeMillis。
1或者2成立即可逐出,注意是或的关系。
所以,结论如下:
如果要连接池只根据softMinEvictableIdleTimeMillis进程逐出,那么需要将minEvictableIdleTimeMillis设置为负数(即最大值);
如果要连接池只根据minEvictableIdleTimeMillis进程逐出,那么需要将softMinEvictableIdleTimeMillis设置为负数(即最大值),理论上设置minIdle很大也是可以的,但是实际上不行;
jedis连接池参数minEvictableIdleTimeMillis和softMinEvictableIdleTimeMillis探索的更多相关文章
- Jedis连接池
jedis是官方首选的java客户端开发包 Redis不仅是使用命令来操作,现在基本上主流的语言都有客户端支持,比如java.C.C#.C++.php.Node.js.Go等. 在官方网站里列一些Ja ...
- 详解Jedis连接池报错处理
在使用Jedis连接池模式下,比较常见的报错如下: redis.clients.jedis.exceptions.JedisConnectionException:Could not get a re ...
- 为什么要用Jedis连接池+浅谈jedis连接池使用
为什么要使用Jedis连接池 Redis作为缓存数据库理论上和MySQL一样需要客户端和服务端建立起来连接进行相关操作,使用MySQL的时候相信大家都会使用一款开源的连接池,例如C3P0.因为直连会消 ...
- Java Redis系列3(Jedis的使用+jedis连接池技术)
Jedis的使用 什么是Jedis? 一款Java操作redis数据库的工具 使用步骤 1.下载redis所需的java包 2.使用步骤 import org.junit.Test; public c ...
- Java与redis交互、Jedis连接池JedisPool
Java与redis交互比较常用的是Jedis. 先导入jar包: commons-pool2-2.3.jar jedis-2.7.0.jar 基本使用: public class RedisTest ...
- C3P0连接池参数配置说明
C3P0连接池参数配置说明 created by cjk on 2017.8.15 常用配置 initialPoolSize:连接池初始化时创建的连接数,default : 3(建议使用) minPo ...
- Spring Boot为我们准备了最佳的数据库连接池方案,只需要在属性文件(例如application.properties)中配置需要的连接池参数即可。
Spring Boot为我们准备了最佳的数据库连接池方案,只需要在属性文件(例如application.properties)中配置需要的连接池参数即可.
- Jedis与Jedis连接池
1.Jedis简介 实际开发中,我们需要用Redis的连接工具连接Redis然后操作Redis, 对于主流语言,Redis都提供了对应的客户端: https://redis.io/clients 2. ...
- 三、redis学习(jedis连接池)
一.jedis连接池 二.jedis连接池+config配置文件 三.jedis连接池+config配置文件+util工具类 util类 public class JedisPoolUtils { / ...
随机推荐
- ubuntu学习笔记
Linux操作系统 locale –a查看支持语言 ls查看目录 ls .l / 查看根目录 apt-get –h 安装软件看帮助信息 sudo apt-get inatall packge 安装包 ...
- xml转json和实体类的两种方式
本文为博主原创,未经允许不得转载: xml在http通信中具有较高的安全性和传输速度,所以应用比较广泛, 在项目中往往需要对xml,json和实体类进行相互转换,在这里总结一下自己所用到的一些方法: ...
- 后台获取POST方式提交的JSON格式数据
1.直接使用request.getParamater()的方法获取(这种取参方式对于POST和GET的提交方式均适用): 2.通过请求体的IO流获取参数(这种方式只能用于POST,因为GET方式没有请 ...
- 分布式消息通信Kafka-原理分析
本文目标 TopicPartition 消息分发策略 消息消费原理 消息的存储策略 Partition 副本机制 1 关于 Topic 和 Partition 1.1 Topic 在 kafka 中, ...
- rocketMQ No route info of this topic 错误
最近在使用rocketmq 发送消息,出现了No route info of this topic 异常,但奇怪的是我的其它的服务都可以成功发送,唯有crs服务不能成功发送,在网上搜索的解决方式基本上 ...
- Python面向对象编程 -- 类和实例、访问限制
面向对象编程 Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 面向过程的程序设计把计算机程 ...
- c#+Unity3D
Windows系统unity3d中的快捷键 自己整理常用; f2 改名 shift + 三维轴中间:45度 点击左键时 F:聚焦 V顶点贴合 ws拉近拉远 ad左右 qe 上下 长按右键 自由调换视角 ...
- vue keep-alive 取消某个页面缓存问题
keep-alive keep-alive是Vue提供的一个抽象组件,用来对组件进行缓存,从而节省性能,由于是一个抽象组件,所以在v页面渲染完毕后不会被渲染成一个DOM元素 <keep-aliv ...
- hbase-0.92.1过滤器学习
查看当前hbase中支持的过滤器 hbase(main):060:0* show_filters Documentation on filters mentioned below can be fou ...
- VMware下Debian开发环境部署之常见问题记录
本文讲介绍windows作为宿主机,linux虚拟机作为编译环境的开发环境搭建中最常用到的三个问题,详细描述了解决过程. 目录: 1.网路配置: 2.分辨率设置: 3.共享网盘设置: 1.网络设置,V ...