Jedis Exception Attempting to read from a broken connection

1,314 views
Skip to first unread message

akash gupta

unread,
Sep 29, 2021, 11:22:09 AM9/29/21
to Jedis
I'm using Jedis to perform   insertions/reads in Redis.
The problem only appears when I start using a few threads (like 9) and the exception is:

 Exception Details: redis.clients.jedis.exceptions.JedisConnectionException: Attempting to read from a broken connection

I've searched a lot about this problem but couldn't find the reason of it or it's solve. The code I'm using to perform these tests is below:

public class RedisClient {
final JedisPoolConfig poolConfig = buildPoolConfig();
JedisPool pool;
public Jedis jedis;

public RedisClient() {
String redisUrl = "localhost"
pool = new JedisPool(poolConfig, redisUrl,10*1000);
int retry=3;
while (retry>0) {
try {
jedis = pool.getResource();
break;
} catch (Exception e) {
retry--;
if(retry==0)
throw new RuntimeException("Unable to connect to Redis" + e);
}
}
}

private JedisPoolConfig buildPoolConfig() {
final JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(128);
poolConfig.setMaxIdle(128);
poolConfig.setMinIdle(16);
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
poolConfig.setTestWhileIdle(true);
poolConfig.setMinEvictableIdleTimeMillis(Duration.ofSeconds(60).toMillis());
poolConfig.setTimeBetweenEvictionRunsMillis(Duration.ofSeconds(30).toMillis());
poolConfig.setNumTestsPerEvictionRun(3);
poolConfig.setBlockWhenExhausted(true);
poolConfig.setMaxWaitMillis(1000);
return poolConfig;
}

/**
* Set User Key
*
* @param siteName
* @param user
* @param userLabel
* @return boolean
*/
public boolean setUserKey(String siteName, User user, String userLabel) {
String key = siteName + "|" + userLabel;
try {
jedis.set(key, user.getUserId());
if (jedis.exists(key)) {
close();
return true;
} else {
throw new RuntimeException("Unable to set key: " + key + " with value: " + user.getUserId() + " on redis server");
}
} catch (Exception e) {
throw new RuntimeException("Unable to set key: " + key + " with value: " + user.getUserId() + " on redis server");
}
}

/**
* @param siteName
* @param userLabel
* @return
*/
public String getUserKey(String siteName, String userLabel) {
String key = siteName + "|" + userLabel;
String value;
try {
// do operations with jedis resource
value = jedis.get(key);
if (!value.isEmpty()) {
close();
return value;
} else {
throw new RuntimeException("Unable to get key: " + key);
}
} catch (Exception e) {
throw new RuntimeException("Unable to get key: " + key + "\n Exception Details: " + e);
}
}

public void close() {
jedis.close();
}
}

any heads up would we good

Allan Wax

unread,
Sep 30, 2021, 8:12:20 PM9/30/21
to Jedis
Perhaps I'm not seeing it but I don't see you returning the resource.  A much safer and efficient way is to use try-with-resource.  I has the adantage of automatically closing/releasing the resource.  Since you've configure it to blocj whenthere are no available connections, do something like this (not actual code)
...
pool = ... create pool ... // only needed once and can be static
...
try (Jedis jedis = pool.getResource()) {
...
do some operations with jedis
...
}

Because Jedis implements AutoClose then try-with-resources will close (actually, return it to the pool) and there is no leakage.

Payal P

unread,
Oct 1, 2021, 6:56:57 PM10/1/21
to Jedis
I ran into a similar issue with multi-threading recently and then the Jedis connection object was behaving odd and it was simply broke. I solved it by what Allan suggested above as it ensures that the connection was auto closed and also fetched using the try-with-resource block which will help in your multi-threading scenario. 

Oscar Besga

unread,
Oct 13, 2021, 3:22:02 PM10/13/21
to Jedis
+ 1 to Allan and Payal
Also, for extra security configure your pool to have test on borrow to true

Reply all
Reply to author
Forward
0 new messages