乐趣区

关于redis:技术干货-高负载压测下接口异常问题定位排查Redis

背景:

xx 业务接口次要为获取全国范畴地区信息,实在生产场景是调用频繁数据量大,因而须要对该业务接口做性能测试,确认接口性能及高负载下承受能力。

接口解决逻辑:获取全国范畴地区信息,第一次从 mysql 获取信息,获取到信息后 hset 到 redis,前面的获取信息都走 redis 获取并返回接口数据。

问题:

20 并发对该接口进行继续加压,压力负载一直晋升,压力机端监控到返回错误信息,连贯失败(10 并发失常),

应用服务抛出异样:getList:merchant:area:list error

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

定位排查:

从利用抛出异样信息看出,无奈获取更多的 redis 线程池资源,但 20 并发还未造成高强度的压力,进一步排查:

硬件资源:服务器资源利用率失常,cpu、内存,磁盘等比拟短缺,排查资源影响

Redis 配置及性能:查看 redis 连接池配置 redis.pool.maxIdle=300,redis.pool.maxTotal=600,设置足够大,在 20 并发继续压测下,该最大连接数已足够大,但依然抛出 redis 连接池异样,应存在其余方面因素影响,持续排查

redis 连接数失常,netstat -nap |grep redis |wc -l,100 多个流动连贯。

redis -info 查看 redis 信息连贯失常,失常连贯 100 多个。

redis -monitor 获取数据失常,get 和 hget 数据均失常。

查看 redis 日志,找到问题如下问题:

WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add ‘vm.overcommit_memory = 1’ to /etc/sysctl.conf and then reboot or run the command ‘sysctl vm.overcommit_memory=1’ for this to take effect.

优化解决:

从 reid 日志报错信息看出,需调节 linux 内核参数

vim /etc/sysctl.conf,减少 vm.overcommit_memory=1,而后 sysctl -p 使配置文件失效

备注:内核参数 vm.overcommit_memory 代表内存调配策略,取值为 0、1、2:

示意内核将查看是否有足够的可用内存供给用过程应用;

如果有足够的可用内存,内存申请容许;

否则,内存申请失败,并把谬误返回给利用过程。

1,示意内核容许调配所有的物理内存,而不论以后的内存状态如何。

2,示意内核容许调配超过所有物理内存和替换空间总和的内存

相干问题信息:

① 当 jedispool 中的 jedis 被取完 期待超过你设置的 MaxWaitMillis 就会抛出 Could not get a resource from the pool

从 GenericObjectPool 源代码 borrowObject(long borrowMaxWaitMillis) 办法能够看出

if(p == null) {

if(borrowMaxWaitMillis < 0L) {

p = (PooledObject)this.idleObjects.takeFirst();

} else {

waitTime = System.currentTimeMillis();

p = (PooledObject)this.idleObjects.pollFirst(borrowMaxWaitMillis, TimeUnit.MILLISECONDS);

waitTime = System.currentTimeMillis() – waitTime; // 等待时间超过 borrowMaxWaitMillis 的时候 p =null

}

}

if(p == null) {

throw new NoSuchElementException(“Timeout waiting for idle object”); 抛出异样 被 pool 这个类捕获

}

pool 源码

try {

return this.internalPool.borrowObject();

} catch (Exception var2) {

throw new JedisConnectionException(“Could not get a resource from the pool”, var2);

}

所以只有把 jedis 配置 MaxWaitMillis 设置的大一点 就能够升高 因为 MaxWaitMillis 导致的

Could not get a resource from the pool,设置太大会造高负载并发下硬件性能的大量开销,可依据压测指标并发数据失去正当的参数设置,及达到较好性能也不至于服务器资源适度耗费

②、放慢从 jedispool 中获取 get jedis 和 return jedis 的 速度

设置 testOnBorrow、testOnReturn 都改为 false

在这两个配置为 true 的状况下 get、return jedis 的时候 jedis 将 ping 一下 redis。

从 GenericObjectPool 源代码 borrowObject(long borrowMaxWaitMillis) 办法能够看出:

if(p != null && (this.getTestOnBorrow() || create && this.getTestOnCreate())) {

boolean validate = false;

Throwable validationThrowable1 = null;

try {

validate = this.factory.validateObject(p);

获取间接先验证是否能够用

} catch (Throwable var13) {

PoolUtils.checkRethrow(var13);

validationThrowable1 = var13;

}

JedisFactory 源代码 validateObject(PooledObjectpooledJedis) 办法能够看出

BinaryJedis jedis = (BinaryJedis)pooledJedis.getObject();

try {

return jedis.isConnected() && jedis.ping().equals(“PONG”);

} catch (Exception var4) {

return false;

}

根本以上这么批改 就可能解决 Could not get a resource from the pool

操作 jedis 的时候 设置 testOnBorrow、testOnReturn 都改为 false,要比 true 快上 1.4 倍,但可能带来的问题可进一步钻研。

退出移动版