lua 函数 默认值_JedisPool 资源池优化及常见问题汇总

背景

合理的 JedisPool 资源池参数设置能为业务使用 Redis 保驾护航,本文将对 JedisPool 的使用、资源池的参数进行详细说明,最后给出“最合理”配置。

一、使用方法

以官方的 3.0.1 为例子(Jedis Release),Maven 依赖如下:

redis.clients

jedis

3.0.1

compile

Jedis 使用 apache commons-pool2 对 Jedis 资源池进行管理,所以在定义 JedisPool 时一个很重要的参数就是资源池 GenericObjectPoolConfig,使用方式如下,其中有很多资源管理和使用的参数(具体看第二节)。注意:后面会提到建议用 JedisPoolConfig 代替 GenericObjectPoolConfig

GenericObjectPoolConfig jedisPoolConfig = new GenericObjectPoolConfig();

jedisPoolConfig.setMaxTotal(..);

jedisPoolConfig.setMaxIdle(..);

jedisPoolConfig.setMinIdle(..);

jedisPoolConfig.setMaxWaitMillis(..);

JedisPool 的初始化如下:

// redisHost和redisPort是实例的IP和端口,redisPassword是实例的密码

// timeout,这里既是连接超时又是读写超时,从Jedis 2.8开始有区分connectionTimeout和soTimeout的构造函数

JedisPool jedisPool = new JedisPool(jedisPoolConfig, redisHost, redisPort, timeout, redisPassword);

Jedis jedis = null;

try {

jedis = jedisPool.getResource();

//具体的命令

jedis.executeCommand()

} catch (Exception e) {

logger.error(e.getMessage(), e);

} finally {

//注意这里不是关闭连接,在JedisPool模式下,Jedis会被归还给资源池。

if (jedis != null)

jedis.close();

}

二、参数说明

JedisPool 保证资源在一个可控范围内,并且提供了线程安全,但是一个合理的 GenericObjectPoolConfig 配置能为应用使用 Redis 保驾护航,下面将对它的一些重要参数进行说明和建议:

在当前环境下,Jedis 连接就是资源,JedisPool 管理的就是 Jedis 连接。

1. 资源设置和使用

序号

参数名

含义

默认值

使用建议

1

maxTotal

资源池中最大连接数

8

设置建议见下节

2

maxIdle

资源池允许最大空闲的连接数

8

设置建议见下节

3

minIdle

资源池确保最少空闲的连接数

0

设置建议见下节

4

blockWhenExhausted

当资源池用尽后,调用者是否要等待。只有当为 true 时,下面的 maxWaitMillis 才会生效

true

建议使用默认值

5

maxWaitMillis

当资源池连接用尽后,调用者的最大等待时间(单位为毫秒)

-1:表示永不超时

不建议使用默认值

6

testOnBorrow

向资源池借用连接时是否做连接有效性检测(ping),无效连接会被移除

false

业务量很大时候建议设置为 false(多一次 ping 的开销)。

7

testOnReturn

向资源池归还连接时是否做连接有效性检测(ping),无效连接会被移除

false

业务量很大时候建议设置为 false(多一次 ping 的开销)。

8

jmxEnabled

是否开启 jmx 监控,可用于监控

true

建议开启,但应用本身也要开启

2.空闲资源监测

空闲 Jedis 对象检测,下面四个参数组合来完成,testWhileIdle 是该功能的开关。

序号

参数名

含义

默认值

使用建议

1

testWhileIdle

是否开启空闲资源监测

false

true

2

timeBetweenEvictionRunsMillis

空闲资源的检测周期(单位为毫秒)

-1:不检测

建议设置,周期自行选择,也可以默认也可以使用下面 JedisPoolConfig 中的配置

3

minEvictableIdleTimeMillis

资源池中资源最小空闲时间(单位为毫秒),达到此值后空闲资源将被移除

1000 * 60 * 30 = 30 分钟

可根据自身业务决定,大部分默认值即可,也可以考虑使用下面 JeidsPoolConfig 中的配置

4

numTestsPerEvictionRun

做空闲资源检测时,每次的采样数

3

可根据自身应用连接数进行微调,如果设置为-1,就是对所有连接做空闲监测

为了方便使用,Jedis 提供了 JedisPoolConfig,它本身继承了 GenericObjectPoolConfig 设置了一些空闲监测设置

public class JedisPoolConfig extends GenericObjectPoolConfig {

public JedisPoolConfig() {

// defaults to make your life with connection pool easier :)

setTestWhileIdle(true);

//

setMinEvictableIdleTimeMillis(60000);

//

setTimeBetweenEvictionRunsMillis(30000);

setNumTestsPerEvictionRun(-1);

}

}

所有默认值可以从 org.apache.commons.pool2.impl.BaseObjectPoolConfig 中看到。

三、资源池大小(maxTotal)、空闲(maxIdle minIdle)设置建议

1.maxTotal:最大连接数

实际上这个是一个很难回答的问题,考虑的因素比较多:

业务希望 Redis 并发量

客户端执行命令时间

Redis 资源:例如 nodes(例如应用个数) * maxTotal 是不能超过 Redis 的最大连接数。

资源开销:例如虽然希望控制空闲连接,但是不希望因为连接池的频繁释放创建连接造成不必靠开销。

以一个例子说明,假设:

一次命令时间(borrow|return resource + Jedis 执行命令(含网络) )的平均耗时约为 1ms,一个连接的 QPS 大约是 1000

业务期望的 QPS 是 50000

那么理论上需要的资源池大小是 50000 / 1000 = 50 个。但事实上这是个理论值,还要考虑到要比理论值预留一些资源,通常来讲 maxTotal 可以比理论值大一些。

但这个值不是越大越好,一方面连接太多占用客户端和服务端资源,另一方面对于 Redis 这种高 QPS 的服务器,一个大命令的阻塞即使设置再大资源池仍然会无济于事。

2. maxIdle minIdle

maxIdle 实际上才是业务需要的最大连接数,maxTotal 是为了给出余量,所以 maxIdle 不要设置过小,否则会有 new Jedis(新连接)开销,而 minIdle 是为了控制空闲资源监测。

连接池的最佳性能是 maxTotal = maxIdle ,这样就避免连接池伸缩带来的性能干扰。但是如果并发量不大或者 maxTotal 设置过高,会导致不必要的连接资源浪费。

可以根据实际总 OPS 和调用 Redis 客户端的规模整体评估每个节点所使用的连接池。

3.监控

实际上最靠谱的值是通过监控来得到“最佳值”的,可以考虑通过一些手段(例如 jmx)实现监控,找到合理值。

四、常见问题

1.资源“不足"

redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

Caused by: java.util.NoSuchElementException: Timeout waiting for idle object

at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:449)

或者

redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

Caused by: java.util.NoSuchElementException: Pool exhausted

at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:464)

两种情况均属于无法从资源池获取到资源,但第一种是超时,第二种是因为 blockWhenExhausted 为 false 根本就不等。

遇到此类异常,不要盲目的认为资源池不够大,第三节已经进行了分析。具体原因可以排查:网络、资源池参数设置、资源池监控(如果对 jmx 监控)、代码(例如没执行 jedis.close())、慢查询、DNS 等问题。

2. 预热 JedisPool

由于一些原因

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值