redis / jedis

Redis Java client
MIT License
11.7k stars 3.85k forks source link

JedisPooled ## Could not get a resource from the pool #3845

Open ashok-mariyala opened 1 month ago

ashok-mariyala commented 1 month ago

Expected behavior

Java Jedis client work with thousands of reads and write on redis server.

Actual behavior

Jedis client gives Could not get a resource from the pool error while performing huge write and read operations on redis client

Stack trace

Error : Could not get a resource from the pool
redis.clients.jedis.exceptions.JedisException: Could not get a resource from the pool
        at redis.clients.jedis.util.Pool.getResource(Pool.java:42) ~[jedis-4.4.3.jar:?]
        at redis.clients.jedis.ConnectionPool.getResource(ConnectionPool.java:29) ~[jedis-4.4.3.jar:?]
        at redis.clients.jedis.ConnectionPool.getResource(ConnectionPool.java:7) ~[jedis-4.4.3.jar:?]
        at redis.clients.jedis.providers.PooledConnectionProvider.getConnection(PooledConnectionProvider.java:68) ~[jedis-4.4.3.jar:?]
        at redis.clients.jedis.executors.DefaultCommandExecutor.executeCommand(DefaultCommandExecutor.java:23) ~[jedis-4.4.3.jar:?]
        at redis.clients.jedis.UnifiedJedis.executeCommand(UnifiedJedis.java:183) ~[jedis-4.4.3.jar:?]
        at redis.clients.jedis.UnifiedJedis.set(UnifiedJedis.java:651) ~[jedis-4.4.3.jar:?]
        at com.ashok.redis.manager.RedisCacheStore.putCache(RedisCacheStore.java:155) ~[redis-manager-17.1.0.jar:?]
Caused by: java.lang.InterruptedException
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.reportInterruptAfterWait(Unknown Source) ~[?:?]
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(Unknown Source) ~[?:?]
        at org.apache.commons.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:594) ~[commons-pool2-2.8.0.jar:2.8.0]
        at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:437) ~[commons-pool2-2.8.0.jar:2.8.0]
        at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:354) ~[commons-pool2-2.8.0.jar:2.8.0]
        at redis.clients.jedis.util.Pool.getResource(Pool.java:38) ~[jedis-4.4.3.jar:?]
        ... 27 more

Steps to reproduce:

Please create a reproducible case of your problem. Make sure that case repeats consistently and it's not random

  1. Deploy Redis standalone deployment in Kubernetes cluster
  2. Deploy Java Application with Jedis client in the same Kubernetes cluster
  3. Perform reads and writes with JedisPooled class

Java Code Snippets Redis connection initialization

JedisPooled jedisPool = null;
private RedisCacheStore( ) {
    initRedisConnection();
}

private void initRedisConnection() {
    try {
                jedisPool = new JedisPooled("redis", 6379, timeout, "default", "Ashok@Redis");
    } catch(Exception e) {
        e.printStackTrace()     
       }
}

Inserting data to the redis server

public boolean putCache(String storeName, String key, String value) throws Exception {  
        String data = jedis.get(storeName);
        JsonObject json;
        if (data == null) {
            json = new JsonObject();
        } else {
            Gson gson = new Gson();
            json = gson.fromJson(data, JsonObject.class);
        }

        synchronized (jo) {
            jo.addProperty(key, value);
                jedis.set(storeName,jo.toString());
            return true;
    }
}

Redis / Jedis Configuration

Jedis version:

4.4.3

Redis version:

redis:7.2.4-debian-11-r0

Java version:

11.0.20.1

sazzad16 commented 1 month ago

@ashok-mariyala The code looks awfully similar to the code in #3838 and #3844. Is the exception mentioned there resolved?

ashok-mariyala commented 1 month ago

@sazzad16 Thank you for the quick response. As you mentions, #3838 and #3844 these 2 tickets used JedisPool where as I am using JedisPooled class. BTW Those are not related to my application codebase. I have taken above tickets reference few days back may be due to that you observed similar code base. Kindly please help me, what might be issue in my code base. Thanks in advance.

sazzad16 commented 1 month ago

You are using new JedisPooled("redis", 6379, timeout, "default", "Ashok@Redis") constructor which uses the default pool config of size 8. As you are performing huge write and read operations, you should allow a larger pool size. You can do that by GenericObjectPoolConfig<Connection> (or simply ConnectionPoolConfig). You can learn more about pool configuration by studying apache commons pool version 2. Here is a short guide on Configuring Connection pool.

ashok-mariyala commented 1 month ago

@sazzad16 Sure I will try to increase the pool size. Could you please suggest me, what is suggestable connection pool recommendation (max total, min idle, max idle) for production grade for huge writes and reads. Thanks in advance.

sazzad16 commented 1 month ago

@ashok-mariyala Sorry, I can't. These depend on application, system, network, design, strategy, etc. You would have to tune accordingly.

If you have a huge number of operations, the number of connections could be one thousand or even several thousands.