文章目录
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, 大于时则直接关闭连接,否则添加回等待队列