Redis 客户端之 Jedis ——JedisPool 分析
文章目录
Jedis
jedis 是 redis 官方推荐的 java 客户端,目前稳定的版本是 2.9.0
JedisPool
jedisPool 是 Jedis 内部管理到 redis 的连接资源,内部的实例是 Jedis,通过连接池策略来优化对 redis 的访问。
JedisPoolConfig
JedisPoolConfig
是创建 JedisPool
的配置类,继承自 Apache
的 GenericObjectPoolConfig
GenericObjectPoolConfig 类各参数默认值和意义:
blockWhenExhausted 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
evictionPolicyClassName 设置的逐出策略类名, 默认DefaultEvictionPolicy(当连接超过最大空闲时间,或连接数超过最大空闲连接数)
lifo 是否启用后进先出, 默认true
maxTotal 最大连接数, 默认8个(连接池能创建的最大连接数量)
maxIdle 最大空闲连接数, 默认8个(在连接 return 到 连接池时,如果空闲连接数 == maxIdle 则直接关闭连接,一般建议该值和 maxTotal 相等)
minIdle最小空闲连接数, 默认0 (该参数会保证 连接池 中在没有达到 maxTotal 时,一直会保持 minIdle 的空闲连接数,但是定时任务是否启动,由下一个参数决定)
maxWaitMillis 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间, 默认-1
timeBetweenEvictionRunsMillis 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
minEvictableIdleTimeMillis 逐出连接的最小空闲时间 默认1800000毫秒(30分钟)
numTestsPerEvictionRun 每次逐出检查时 逐出的最大数目 如果为负数就是 : idle.size()/abs(n), 默认3
softMinEvictableIdleTimeMillis 对象空闲多久后逐出, 当空闲时间>该值 且 空闲连接>最大空闲数 时直接逐出,不再根据MinEvictableIdleTimeMillis判断 (默认逐出策略)
testOnBorrow 在获取连接的时候检查有效性, 默认false
testWhileIdle 在空闲时检查有效性, 默认false
testOnCreate 在创建连接时检查有效性, 默认 false
testOnReturn 在返回连接时检查有效性, 默认 false
JedisPoolConfig
类如下:
public class JedisPoolConfig extends GenericObjectPoolConfig {
public JedisPoolConfig() {
// defaults to make your life with connection pool easier :)
setTestWhileIdle(true);
setMinEvictableIdleTimeMillis(60000);
setTimeBetweenEvictionRunsMillis(30000);
setNumTestsPerEvictionRun(-1);
}
}
不同点
-
JedisPoolConfig
设置testWhileIdle
为true
,此参数设置定时任务检查空闲连接,具体的定时任务由下面的参数配置 -
minEvictableIdleTimeMillis=60000
表示连接空闲 1 分钟,则直接关闭 -
timeBetweenEvictionRunsMillis=30000
表示定时任务间隔30s执行一次,小于 0 时则不执行 -
numTestsPerEvictionRun=-1
表示每次逐出的空闲连接数量,为负数时 idle.size()/abs(n)
JedisPool检查策略
如何** JedisPool evict schedule
JedisPool
内部实际持有的是 Apache
的 GenericObjectPool
,所有实际的操作都有 GenericObjectPool
实现,我们直接撸代码,下图中红色方框标出的定时任务的入口
timeBetweenEvictionRunsMillis
这个参数会控制 Evictor
是否启动,当小于 0 时,定时任务不启动,JedisPoolConfig
默认值30000ms
, GenericsObjectPoolConfig
默认值是 -1
Evictor Timer 的作用
Evictor extends TimerTask
,具体的实现如下:
- 首先执行
evict()
方法 - 然后在执行
ensureMinIdle()
方法
接下来,我们看下evict()
方法内部到底干了些什么
-
先判断
idle
的阻塞队列中是否有空闲连接 -
然后直接根据我们设置的参数创建
EvictionConfig
对象 -
for 循环来处理空闲的连接
-
执行
evict(config, underTest, idleCount)
方法来判断是否逐出连接,如果不逐出,同时testOnIlde
为true
时,则检查连接的有效性,不有效则destroy
该连接,会从idle
的队列中移除,具体的关闭方法则不看了具体的判断关闭连接的方法我们来看下,有两个条件
- 一个是 空闲时间超过最小空闲时间,则直接关闭
- 另一个是共享的连接数大于 我们设置的最小空闲连接,同时该连接的空闲时间要大于
softMinEvictableIdleTimeMillis
,该值的默认值是 -1,所以该条件只需要判断 空闲 连接是否大于我们设置的minIdle
-
让我们看下
ensureMinIdle()
的真容吧该方法内部调用的是一个重载的方法,传入的参数是我们设置的
minIdle
和true
如果最小空闲连接小于1 或者 连接池关闭 则直接返回,
否则会进入到一个 while 循环,当空闲连接小于我们设置的 minIdle 时,则会创建新连接并添加到idleObjects
队列中,直到空闲连接 >=minIdle
,或者创建连接失败
注意- 使用 GenericObjectPoolConfig 该配置类时,需要自己设置启动的检查参数,不然 minIdle 和 maxIdle 都无效,同时建立的所有连接都不会关闭
- 该空闲检查任务总是会先关闭达到空闲条件的连接,同时创建新连接直到达到最小空闲连接数
maxIdle 的用处
在 returnObject
的方法中,首先会判断该连接的状态是否是被分配的,如果状态异常则抛出异常,否则执行 markReturning()
方法,该方法只是把该连接的状态标记为 return
如果 testOnReturn
为 ture
则会 validateObject()
来验证连接是否是健康的,不健康则调 destroy
方法销毁,同时会保证连接池中至少有 1
个空闲连接
passivateObject()
这个方法内部没有实现
接下来才是真正的放回 idleObjects
空闲队列, 先会判断 idleObjects
队列中的空闲连接数量是否大于 maxIdle
, 大于时则直接关闭连接,否则添加回等待队列