Jedis是Redis官方提供的java客户端,是一款便于使用和性能较佳的redis客户端工具。 其他说明可以参考Jedis文档。
合理的Jedis连接池参数设置能够有效地提升客户端使用Redis性能。本文将对Jedis的使用和连接池的参数进行说明,并提供优化配置的建议。
使用方法
以 jedis 4.3.1版本为例,下面是maven依赖配置:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.1</version>
</dependency>
Jedis使用Apache Commons-pool2对连接池进行管理,在定义JedisPool时需注意其关键参数GenericObjectPoolConfig(连接池)。该参数的使用示例如下,其中的参数的说明请参见下文。
GenericObjectPoolConfig<Jedis> config = new GenericObjectPoolConfig<>();
config.setMaxTotal(100);
config.setMaxIdle(50);
config.setMinIdle(5);
config.setTestWhileIdle(true);
....
Jedis的初始化方法如下:
JedisPool pool = new JedisPool(config, host, port, timeout, password);//创建连接池
try (Jedis jedis = pool.getResource()) { //获取连接,执行完自动释放连接
//利用jedis客户端执行命令
} catch (Exception e) {
e.printStackTrace();
}
pool.close();//关闭连接池
参数说明
Jedis连接就是连接池中JedisPool管理的资源,JedisPool保证连接在一个可控范围内,并且保障线程安全。使用合理的GenericObjectPoolConfig配置能够提升Redis的服务性能,降低资源开销。下列两表将对一些重要参数进行说明,并提供设置建议。
表1. GenericObjectPoolConfig参数说明
参数 说明 默认值 建议 maxTotal 连接池的最大连接数 8 参考下面的参数设置建议 maxIdle 连接池的最大空闲连接数 8 参考下面的参数设置建议 minIdle 连接池确保的最少空闲连接,不足的会新建连接 0 参考下面的参数设置建议 blockWhenExhausted 当连接池的连接用尽后,获取新连接是否会阻塞等待。
true: 会阻塞直到获取新连接或maxWaitMillis时间到了, 抛出异常.
false: 会直接抛出异常
true 建议使用默认值 maxWaitMillis 当连接池的连接用尽后,获取连接的最大等待时间(单位毫秒),-1表示一直阻塞 -1 建议设置一个合理的超时时间,避免出现当连接池用尽后,应用阻塞不响应的情况 testOnBorrow 每次向连接池获取连接时是否做连接有效性检测(发送PING请求)。无效连接会被释放 false 建议使用默认值。设为true相当于在每个命令执行完前先发一个PING命令,对高并发请求大应用的性能有影响。
对于业务可用性要求比较高的场景,可以设为true,可以保证连接有效的。
testOnReturn 每次向连接池归还连接时是否做连接有效性检测(发送PING请求),无效连接会被释放 false 建议使用默认值。设为true相当于在每个命令执行完后再发一个PING命令,对高并发请求大应用的性能有影响。 lifo 连接池管理连接的方式是否使用LIFO方式
true使用LIFO(后进先出)方式
false使用FIFO(先进先出)方式
true 建议使用默认值。 fairness 并发获取连接时,是否按并发的先后顺序从连接池获取 false 建议使用默认值。 false的情况,性能更佳a jmxEnabled 是否开启jmx监控 true 建议使用默认值,同时应用也需要开启 testWhileIdle 是否检测空闲连接的有效性,无效连接会被释放
只在timeBetweenEvictionRunsMillis > 0时有效
false 建议使用true。也可使用JedisPoolConfig。 timeBetweenEvictionRunsMillis 空闲连接的检测周期(单位毫秒),-1表示不开启空闲连接检测 -1 建议建议设置,周期自行选择。也可使用JedisPoolConfig minEvictableIdleTimeMillis 最小空闲时间(单位毫秒)。空闲连接检测时,如果连接在最小空闲时间内都没有被获取使用,则会被释放。-1表示不释放,
只在timeBetweenEvictionRunsMillis > 0有效1800000(30分钟) 根据业务决定,一般使用默认值即可。也可使用JedisPoolConfig的配置 numTestsPerEvictionRun 检测空闲连接时,每次检测的连接数,如果为负数-n,则表示检测1/n个连接 3 可根据业务需求设置。
Jedis也提供了参考的JedisPoolConfig类。由于jedis、spring data redis等SDK默认使用的是JedisPoolConfig类,而JedisPoolConfig类继承自GenericKeyedObjectPoolConfig类。JedisPoolConfig为了方便使用在构造函数中设置了一些参数,具体如下:
public class JedisPoolConfig extends GenericObjectPoolConfig<Jedis> {
public JedisPoolConfig() {
// defaults to make your life with connection pool easier :)
setTestWhileIdle(true);
setMinEvictableIdleTime(Duration.ofMillis(60000));
setTimeBetweenEvictionRuns(Duration.ofMillis(30000));
setNumTestsPerEvictionRun(-1);
}
}
这些参数对JedisPool连接池的具体含义是:JedisPool连接池默认最多有8个连接,最多有8个空闲连接,同时开启空闲连接检测,每30s检测一次(且会通过发送PING命令,检测连接的有效性),如果有连接60s内仍然处于空闲状态(60s内一直没有使用)或无效(连接异常),该连接就会被释放,一次释放一个。
参数设置建议
maxTotal、maxIdle、minIdle的关系
这些参数在连接池中的含义是:maxTotal是连接池的容量,包括空闲连接和使用中的连接。将连接归还给连接池时,如果空闲连接数超过maxIdle,会被直接释放。同时连接池还要保证其中至少要有minIdle个空闲连接,如果不足也会新建连接加入其中。
maxTotal
想合理设置maxTotal(最大连接数)需要考虑的因素较多,如:
- 业务要求的Redis并发量;
- 命令执行时间;
- Redis连接数限制,例如 客户端连接池个数 * maxTotal不能超过Redis的最大连接数
- 资源开销, 不希望有多余的空闲连接浪费资源,但也不希望连接不够导致创建连接造成不必要的开销
假设一次命令时间,包括获取连接、发送请求到得到响应(含网络耗时)的平均耗时约为1ms。 一个连接的QPS大约是1sec / 1ms = 1000,而业务期望的单个Redis的QPS是10000,那么理论上需要的连接池大小(即MaxTotal)是10000 / 1000 = 10。
但理论值也仅需参考,因为实际的运行情况和业务压力是动态变化的。 可能遇到突发的高压力的场景,需要更多的TPS。也可能Redis遇到出现大命令导致阻塞,即使设置再大的资源池也无济于事。
maxIdle和minIdle
maxIdle和minIdle是最影响业务的参数, 分别控制可用连接数的上下限。
连接池的最佳性能是maxTotal = maxIdle ,这样就避免了连接池伸缩带来的性能干扰。如果您的业务存在突峰压力,建议设置这两个参数的值相等;如果redis请求的压力不大,则会导致不必要的连接资源浪费。
总的来说, 可以根据实际总QPS和调用Redis的客户端规模整体评估每个节点所使用的连接池大小。
使用监控获取合理值
在实际环境中,比较可靠的方法是通过监控来尝试获取参数的最佳值。可以考虑通过JMX等方式实现监控,从而找到合理值。