redis / jedis

Redis Java client

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Could not get a resource from the pool

nageswarao-pragada opened this issue · comments

Expected behavior

Getting the error when I try to perform get, put operations. I want to perform without facing any issue.
suggest jedis connection settings for high performance and reliablity

Actual behavior

I am getting the below error

redis.clients.jedis.exceptions.JedisException: Could not get a resource from the pool
	at redis.clients.jedis.util.Pool.getResource(Pool.java:42) ~[jedis-5.1.2.jar:?]
	at redis.clients.jedis.JedisPool.getResource(JedisPool.java:378) ~[jedis-5.1.2.jar:?]

Steps to reproduce:

I configured the JedisPool like below

var redisHostName = System.getenv("REDIS_HOST");
var redisPort = null !=  System.getenv("REDIS_PORT") ? Integer.parseInt(System.getenv("REDIS_PORT")) : 6379;
var redisUserName = System.getenv("REDIS_USERNAME");
var redisPassword = System.getenv("REDIS_PASSWORD");

GenericObjectPoolConfig<Jedis> poolConfig = new GenericObjectPoolConfig<>();
poolConfig.setMaxTotal(10000); // Set maximum number of connections
poolConfig.setMaxIdle(500);  // Set maximum number of idle connections
poolConfig.setMinIdle(500);   // Set minimum number of idle connections
int timeout = 60000;
	        
 JedisPool jedispool= new JedisPool(poolConfig, redisHostName, redisPort, timeout, redisUserName, redisPassword);

Jedis version:

redis.clients jedis 5.1.2

Java version:

java11

  1. Is your Redis server actually running?
  2. Is your Java application is allowed to access that server?

Above two are first questions that are needed to be answered. With the information provided, it is really difficult to give any suggestion. For example, the exception with message Could not get a resource from the pool is likely to have a Caused by block which could be helpful.

My suggestion is to start with creating a Jedis object first and build up from there.

Thanks for the response
1.Is your Redis server actually running? --> yes

2.Is your Java application is allowed to access that server? --> yes

below is the code

public String getCache(String cacheName, String key) throws Exception {
	try(Jedis jedisPool = jedis.getResource()) {
	String jsonString = jedisPool.get(cacheName);
        Gson gson = new Gson();
        JsonObject jo = gson.fromJson(jsonString, JsonObject.class);
        if (jo != null && jo.has(key)) {
        	return jo.get(key).getAsString();
        }
		}catch (Exception e) {
	        System.out.println("#Failed to get data : {}", e.getMessage(), e);
	    } finally {
	    	if (jedis != null) {
	            jedis.close(); 
	        }
	    }
        	   
	    return null;
	}```

i am getting error at the line  try(Jedis jedisPool = jedis.getResource()){
`
ERROR : 
edis.clients.jedis.exceptions.JedisException: Could not get a resource from the pool
	at redis.clients.jedis.util.Pool.getResource(Pool.java:42) ~[jedis-5.1.2.jar:?]
	at redis.clients.jedis.JedisPool.getResource(JedisPool.java:378) ~[jedis-5.1.2.jar:?]

I am using large application so I need to perform set and get operations multiple times. can you please
suggest according to this perspective

@nageswarao-pragada How can we help when you don't address our suggestions and hints?

  1. Is your Redis server actually running?
  2. Is your Java application is allowed to access that server?

You have provided no reasons to be convinced on your 'Yes' answers.

For example, the exception with message Could not get a resource from the pool is likely to have a Caused by block which could be helpful.

I hinted that a full exception, especially the 'Caused by' block would be more helpful to provide suggestions, but you avoided.

My suggestion is to start with creating a Jedis object first and build up from there.

There is this another suggestion that you ignored.

@sazzad16 Thanks for the response.

As my java application is huge and there thousands of reads and writes will happen per minute, I would like to use JedisPool instead of Jedis.

I have deployed Redis server and My Java application on Kubernetes cluster in the form of Kubernetes POD. My Redis server POD is up and running without any issue.
As my Redis server and Java application is running on same cluster, my application is able to access the redis service using Kubernetes service (redis is the name of my kubernetes service)

Here is the stack track while performing the action in redis

redis.clients.jedis.exceptions.JedisException: Could not get a resource from the pool
	at redis.clients.jedis.util.Pool.getResource(Pool.java:42) ~[jedis-5.1.2.jar:?]
	at redis.clients.jedis.JedisPool.getResource(JedisPool.java:378) ~[jedis-5.1.2.jar:?]
	at com.nag.redis.store.RedisCacheStore.getCache(RedisCacheStore.java:254) ~[content-manager-17.1.0.jar:?]
	at com.nag.redis.store.RedisCacheStore.get(RedisCacheStore.java:305) ~[content-manager-17.1.0.jar:?]
	at com.nag.redis.store.DatastoreClient.get(DatastoreClient.java:19) ~[content-core-12.0.4.jar:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:?]
	at java.lang.Thread.run(Unknown Source) [?:?]
Caused by: java.lang.IllegalStateException: Pool not open
	at org.apache.commons.pool2.impl.BaseGenericObjectPool.assertOpen(BaseGenericObjectPool.java:770) ~[commons-pool2-2.8.0.jar:2.8.0]
	at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:407) ~[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-5.1.2.jar:?]
	... 22 more

Here is the my code snippet.

Redis connection initialization

JedisPool jedisPool = null;

private RedisCacheStore( ) {
		initRedisConnection();
}

private void initRedisConnection() {
	try {
		LOG.info("Trying to initiate redis connection.");
                GenericObjectPoolConfig<Jedis> poolConfig = new GenericObjectPoolConfig<>();
	        poolConfig.setMaxTotal(10000); // Set maximum number of connections
	        poolConfig.setMaxIdle(500);  // Set maximum number of idle connections
	        poolConfig.setMinIdle(500);   // Set minimum number of idle connections
	        int timeout = 60000;		
                jedisPool = new JedisPool(poolConfig, "redis", 6379, timeout, "default", "Redis@12345");
		LOG.info("Successfully initiated redis connection.");
	} catch(Exception e) {
		LOG.error("Failed to initialize redis connection. Error : {} {}", e.getMessage(), e);		
       }
}

Get operation code snippet

public String getCache(String cacheName, String key) throws Exception {
	try(Jedis jedis = jedisPool.getResource()) {
	      String jsonString = jedis.get(cacheName);
              Gson gson = new Gson();
              JsonObject jo = gson.fromJson(jsonString, JsonObject.class);
              if (jo != null && jo.has(key)) {
        	   return jo.get(key).getAsString();
               }
	} catch (Exception e) {
	        LOG.error("#Failed to get data : {}", e.getMessage(), e);
	} finally {
	    	if (jedis != null) {
	            jedis.close(); // Close the Jedis resource in the finally block
	        }
	}	   
	return null;
}

Here I am getting exception jedis.getResource()
Put operation code snippet

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

	        synchronized (jo) {
	            jo.addProperty(key, value);
	            jedisPool.set(storeName, jo.toString());
	            return true;
	        }
	  } catch (Exception e) {
	        LOG.error("#Failed to put data : {}", e.getMessage(), e);
	        return false;
	    } finally {
	        if (jedis != null) {
	            jedis.close(); // Close the Jedis resource in the finally block
	        }
	    } 
	}

Here I am getting exception jedis.getResource()

@sazzad16 Please check the above snippets and let me know if you need further information.

Here is your issue:

Caused by: java.lang.IllegalStateException: Pool not open

Possibly, somewhere in your application jedisPool.close(); is prematurely called.


BTW, I hope jedisPool.set(storeName, jo.toString()); is a mistake and it is supposed to be jedis.set(storeName, jo.toString());.

@sazzad16 Thanks for the response.
Sorry it is jedis.set(storeName, jo.toString()); not jedisPool.set(storeName, jo.toString()); i renamed the variable and forgot to change variable references.
Here is the original code to set the data.

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

	        synchronized (jo) {
	            jo.addProperty(key, value);
	            jedis.set(storeName, jo.toString());
	            return true;
	        }
	  } catch (Exception e) {
	        LOG.error("#Failed to put data : {}", e.getMessage(), e);
	        return false;
	    } finally {
	        if (jedis != null) {
	            jedis.close(); // Close the Jedis resource in the finally block
	        }
	    } 
	}