得到" JedisConnectionException:无法从池中获取资源"有时

时间:2018-03-08 09:22:51

标签: redis connection-pooling jedis object-pooling

我搜索过很多帖子,但无法得到令人满意的答案。

我们使用Jedis Cluster,如:

um.redis.maxActive = 100 um.redis.maxIdle = 10 um.redis.minIdle = 10 um.redis.maxWait = 5000

    GenericObjectPoolConfig config = new GenericObjectPoolConfig();
    config.setMaxTotal(100);
    config.setMaxIdle(100);
    config.setMinIdle(100);
    config.setMaxWaitMillis(1000);

    jedisCluster = new JedisCluster(jedisClusterSet,2000, 500, 3, DispatcherConfigHolder.redisConfig.getUmRedisPassword(), config);

我有一个大型应用程序,每个应用程序都有大tps,可能超过10000个,我们有几个应用程序可以访问redis集群(一个有几十个实例的集群)。

如您所见,为了避免收缩,我们设置minIdle = maxIdle = maxTotol = 100。

但有时,我们得到了一个例外:

   redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
        at redis.clients.util.Pool.getResource(Pool.java:53)
        at redis.clients.jedis.JedisPool.getResource(JedisPool.java:226)
        at redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnectionFromSlot(JedisSlotBasedConnectionHandler.java:66)
        at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:116)
        at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:141)
        at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:141)
        at redis.clients.jedis.JedisClusterCommand.run(JedisClusterCommand.java:31)
        at redis.clients.jedis.JedisCluster.hmget(JedisCluster.java:434)
        at com.oppo.push.open.basic.dao.app.AppDeviceDaoImpl.get(AppDeviceDaoImpl.java:49)
        at com.oppo.push.open.basic.service.AppDeviceServiceImpl.get(AppDeviceServiceImpl.java:56)
        a
t com.oppo.push.open.basic.service.PushTargetServiceImpl.getDeviceId(PushTargetServiceImpl.java:40)
        at com.oppo.push.open.basic.validation.UnicastValidator.validateAndResolveDeviceId(UnicastValidator.java:90)
        at com.oppo.push.open.basic.service.UnicastServiceImpl.pretreat(UnicastServiceImpl.java:227)
        at com.oppo.push.open.basic.service.UnicastServiceImpl.pretreatWithTrace(UnicastServiceImpl.java:240)
        at com.oppo.push.open.basic.service.UnicastServiceImpl.access$000(UnicastServiceImpl.java:67)
        at com.oppo.push.open.basic.service.UnicastServiceImpl$1.call(UnicastServiceImpl.java:162)
        at com.oppo.push.open.basic.service.UnicastServiceImpl$1.call(UnicastServiceImpl.java:157)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.ru
nWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out
        at redis.clients.util.RedisInputStream.ensureFill(RedisInputStream.java:202)
        at redis.clients.util.RedisInputStream.readByte(RedisInputStream.java:40)
        at redis.clients.jedis.Protocol.process(Protocol.java:151)
        at redis.clients.jedis.Protocol.read(Protocol.java:215)
        at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:340)
        at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:239)
        at redis.clients.jedis.BinaryJedis.auth(BinaryJedis.java:2139)
        at redis.clients.jedis.JedisFactory.makeObject(JedisFactory.java:108)
        at org.apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool
.java:868)
        at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:435)
        at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363)
        at redis.clients.util.Pool.getResource(Pool.java:49)
        ... 22 common frames omitted
Caused by: java.net.SocketTimeoutException: Read timed out
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.read(SocketInputStream.java:152)
        at java.net.SocketInputStream.read(SocketInputStream.java:122)
        at java.net.SocketInputStream.read(SocketInputStream.java:108)
        at redis.clients.util.RedisInputStream.ensureFill(RedisInputStream.java:196)
        ... 33 common frames omitted

问题:

1.为什么我们仍然发现池仍在创建实例并且来自源代码

enter image description here

enter image description here

如果我的理解是正确的,从源代码中,连接应该小于100,或者它应该返回null但不创建新的连接,不应该吗?

但我的应用程序运行了一段时间,它肯定处理了超过100个请求。由于我的最小空闲时间也是100,所以应该已经有100个连接,为什么要再次创建新连接?

  1. 根本原因是读取超时,这是什么意思,这个超时有多长? soTimeout(500)或connectionTimeout(2000)或maxWaitMillis(1000)?

  2. 可能的原因是什么?许多请求缓慢,请求太多,或群集遭遇了什么不好?

  3. 有关此泳池配置的任何建议吗?

0 个答案:

没有答案
相关问题