JedisPool资源池优化

背景

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

一、使用方法

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

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
    <scope>compile</scope>
</dependency>

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等问题。

具体可以参考该文章:https://www.atatech.org/articles/77799

2. 预热JedisPool

由于一些原因(例如超时时间设置较小原因),有的项目在启动成功后会出现超时。JedisPool定义最大资源数、最小空闲资源数时,不会真的把Jedis连接放到池子里,第一次使用时,池子没有资源使用,会new Jedis,使用后放到池子里,可能会有一定的时间开销,所以也可以考虑在JedisPool定义后,为JedisPool提前进行预热,例如以最小空闲数量为预热数量


List<Jedis> minIdleJedisList = new ArrayList<Jedis>(jedisPoolConfig.getMinIdle());

for (int i = 0; i < jedisPoolConfig.getMinIdle(); i++) {
    Jedis jedis = null;
    try {
        jedis = pool.getResource();
        minIdleJedisList.add(jedis);
        jedis.ping();
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    } finally {
    }
}

for (int i = 0; i < jedisPoolConfig.getMinIdle(); i++) {
    Jedis jedis = null;
    try {
        jedis = minIdleJedisList.get(i);
        jedis.close();
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    } finally {

    }
}

广告

云数据库Redis版(ApsaraDB for Redis)是一种稳定可靠、性能卓越、可弹性伸缩的数据库服务。基于飞天分布式系统和全SSD盘高性能存储,支持主备版和集群版两套高可用架构。提供了全套的容灾切换、故障迁移、在线扩容、性能优化的数据库解决方案。欢迎各位购买使用:云数据库 Redis 版

招聘:阿里云-技术专家-KVstore

岗位描述:

  • 负责阿里云Redis源码开发维护
  • 负责阿里云Redis cluster开发与设计

岗位要求:

  • 精通C/C++,熟悉TCP, Linux Kernel等优先
  • 数据结构,算法等基础知识扎实
  • 5年后台系统的设计与开发,或3年分布式系统的设计与开发,运维过大型分布式系统
  • 精通至少一项开源NoSQL产品。Redis,mongodb,memcached等优先。
  • 有云服务产品或基于SSD的系统开发经验优先
  • 善于创新,乐于挑战,有责任心,良好团队精神
  • 良好的表达能力,能够清晰和准确地描述问题,发现并解决问题能力
时间: 2024-10-02 13:41:29

JedisPool资源池优化的相关文章

Jedis常见异常汇总

Jedis虽然使用起来比较简单,但是如果不能根据使用场景设置合理的参数(例如连接池参数),不合理的使用一些功能(例如Lua和事务)也会产生很多问题,本文对这些问题逐个说明: 一.无法从连接池获取到Jedis连接 1.异常堆栈 (1) 连接池参数blockWhenExhausted = true(默认) 如果连接池没有可用Jedis连接,会等待maxWaitMillis(毫秒),依然没有获取到可用Jedis连接,会抛出如下异常: redis.clients.jedis.exceptions.Jed

赵慧玲:网络重构之路漫长,SDNFV挑战诸多

4月18日,2017全球未来网络发展峰会SDN/NFV技术与应用论坛于南京江宁隆重召开.会上,中国通信学会常务理事赵慧玲发表了"SDNFV实践与挑战"的主题演讲.赵慧玲表示,网络重构的主要挑战涉及网络层面和运营层面,其中网络层面主要涉及SDN和NFV,而运营层面主要包括网络编排和业务编排两大方面. 据悉,Gartner技术成熟度曲线表明,SDN/NFV已经趋近成熟.数据显示2015到2016年间,运营商采用x86的服务器中47%用于SDN/NFV(OSS/BSS占29%,云关联服务占1

中国电信优化全球节点布局:云资源池数量年底将超过50个

在今天举行的"第九届中国云计算大会"上,中国电信云计算公司副总经理徐守峰作了题为<云+时代的探索者>的主题发言. 徐守峰指出,中国电信今年在云计算方面进行了大胆的布局,在内蒙古和贵州两大集团级资源池的基础上,提出来2+31+X的属地化的资源池格局.新的架构在统一集约的平台和产品的基础上,解决了贴近客户满足客户需求以及网络时延的需求. 不止在国美,中国电信在全球云资源池上也做了大胆的布局调整,到今年年底,中国电信云资源池的数量将会超过五十个. 徐守峰说,中国电信在今年从集团的

ASP.NET性能优化小结(ASP.NET&amp;amp;C#)

ASP.NET: 一.返回多个数据集 检查你的访问数据库的代码,看是否存在着要返回多次的请求.每次往返降低了你的应用程序的每秒能够响应请求的次数.通过在单个数据库请求中返回多个结果集,可以减少与数据库通信的时间,使你的系统具有扩展性,也可以减少数据库服务器响应请求的工作量. 如果用动态的SQL语句来返回多个数据集,那用存储过程来替代动态的SQL语句会更好些.是否把业务逻辑写到存储过程中,这个有点争议.但是我认为,把业务逻辑写到存储过程里面可以限制返回结果集的大小,减小网络数据的流量,在逻辑层也不

浅析渲染引擎与前端优化

本文主要是两方面内容: 浅析浏览器内核的工作原理(以 WebKit 2 为例). 浅析由浏览器内核想到的前端优化,或者说前端优化规则是从哪儿来的. 大家知道,大部分的 WEB 页面依托浏览器呈现,而浏览器能够将页面展示出来,基本依赖于浏览器的内核,即渲染引擎.今天以 Chrome 浏览器的内核 WebKit(更确切是 WebKit 分支 Blink,以下统称为 WebKit )为例,对渲染引擎如何展示页面做个简单.全面的了解. 浏览器的渲染引擎及其依赖模块 渲染引擎主要是将 WEB 资源如 HT

JERSEY作为客户端的性能优化

问题描述 JERSEY作为客户端的性能优化 最近在研究JERSEY框架作为客户端的性能问题,实测结果很不理想,有没有大神可以帮助在下. JERSEY 作为客户端每秒百以上caps发消息,经常出现很多链接超时,导致业务失败且CPU过高,查看jstack堆栈会发现有很多线程BLOCKED,在等某资源. 我大概查了一下JERSEY源码,Client这个客户端类是个很重的类,但是我在代码中是每个请求都new一个Client的,不知道JERSEY有没有比较好的这方面的解决方案,或者需要自己实现一个类似资源

谈大集中系统的性能优化策略

1.1 前言 税务大集中信息系统性能优化方面,我们从技术和业务两个方面,进行前后台架构如何优化.多层架构各层如何优化.编码程序如何优化等,以及对业务的改进和系统功能优化. 技术方面,除了考虑硬件平台.系统资源外,考虑软硬件资源分配等系统性能优化手段,以及应用架构体系.数据库架构的优化;另外,从应用系统编码方面,考虑编码的调整与优化;业务方面,考虑业务规则的调整优化. 1.2 正文 税务大集中信息系统的基本性能保障目标,最起码达到几点要求: 前台税务登记保存时间不超过3秒. 前台申报开票保存时间不

数据库性能优化:五招让IT反败为胜

当数据库的性能变得糟糕时,IT人员能扭转局面. 生产数据库的性能会随着业务和数据的增长而严重迟钝.每一个关键数据库性能的降低都可能会导致全面的业务损失. 从技术上讲,性能优化可以从许多不同的层次下手应用程序可以优化,数据库可以调整,或建立新的系统架构.但是,在生产中,这些问题往往会由IT运维来解决,采取某些对系统破坏性最低的措施实现提速. 以下是IT专业人员对付性能下降问题的一些新方法:但是,必须首先达成共识:为什么应该由IT人说了算? 数据库管理员和开发人员有许多方法可以实现数据库性能调优.他

核心交易系统应用服务器实现资源池化,可行吗?

传统金融企业中,很多已经开始进行了企业私有云建设.落地的建设成果中,大部分实现了存储.网络.服务器的资源池化,而应用服务器部分更多的还是在某个应用服务器给某个应用系统使用,呈现出一定的"烟囱"式.随着应用系统的不断增加,管理这些服务器和部署其上的中间件服务代价也越来越大,将企业应用服务器资源池化,使若干应用系统可以共享使用高可用的企业级中间件服务是众多企业认可的一条解决之道. 经社区调研,中间件的资源池化面临诸多问题,比如共享资源使用冲突.应用系统之间相互影响.运维管理模式变化.功能支