0

Using Tomcat to run a web app. and I use jedis to connect to our redis server.

Every method that I use is call jedis.close() in finallay block but it look like not return the jedis resources to the pool.

using

netstat -atnlp|grep 6379

The connection count is stile grow. Until jedis client throw the "JedisConnectionException: Could not get a resource from the pool.". I debug the code. jdeis.close() is did run.

Is there any problom whit my Code?

Help me, this has already make our server down for many times.

this is my jedis pom conf

<!-- jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.7.3</version>
</dependency>

tomcat is

apache-tomcat-7.0.64

server is

Centos 6.5

redis is

v2.8.11

Spring version:

3.2.13.RELEASE

This is my JedisUtils code:

@Service(value = "redisCacheService")
public class RedisCacheServiceImpl implements CacheService {

    /**
     * redis Version No.
     */
    private static final String VERSION = "000";

    private static JedisPool pool;
    static {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(500);
        config.setMaxIdle(5);
        config.setMaxWaitMillis(1000 * 10);
        config.setTestOnBorrow(true);
        pool = new JedisPool(config, "10.10.65.10", 6379);
    }

    @Override
    public int set(
                    String key,
                    String value) {
        Jedis jedis = pool.getResource();
        try {
            return jedis.set(VERSION + "|" + key, value).equals("OK") ? 1 : 0;
        } finally {
            jedis.close();
        }
    }

    @Override
    public int set(
                    String key,
                    String value,
                    int seconds) {
        Jedis jedis = pool.getResource();
        try {
            return jedis.setex(VERSION + "|" + key, seconds, value).equals("OK") ? 1 : 0;
        } finally {
            jedis.close();
        }
    }

    @Override
    public String get(
                    String key) {
        Jedis jedis = pool.getResource();
        try {
            return jedis.get(VERSION + "|" + key);
        } finally {
            jedis.close();
        }
    }

    @Override
    public int del(
                    String key) {
        Jedis jedis = pool.getResource();
        try {
            return Integer.valueOf(jedis.del(VERSION + "|" + key).toString());
        } finally {
            jedis.close();
        }
    }

    @Override
    public void setExpire(
                    String key,
                    int expireTime) {
        Jedis jedis = pool.getResource();
        try {
            jedis.expire(key, expireTime);
        } catch (Exception e) {
            jedis.close();
        }
    }
}

MORE INFO: 2015-11-28 19:58:50

Now the connection count to redis server is still growth.

using jmap to dump all the heap info, and run OQL on jvisualvm:

select x from redis.clients.jedis.Jedis x

Then I found 24 jedis object.

Then I call the jedis method on the same tomcat server again, and dump again. Run the same OQL, there is 25 jedis object found.

maybe this info is helpful.

BeeNoisy
  • 1,254
  • 1
  • 14
  • 23
  • Look at the implementation of the close operation. I didn't look up what a "broken client" is, but it looks like there are circumstances under which the close call is omitted: https://github.com/xetorthio/jedis/blob/master/src/main/java/redis/clients/jedis/Jedis.java#L3385 (in case this is the code you're running) – Olaf Kock Nov 28 '15 at 17:50
  • Yes,I am call the close method to release the jedis resource. And the resource should be return to the pool, but it didn't happen, using **netstat -antlp | grep 6379 | wc -l** to count the socket number, the number is still growth. – BeeNoisy Nov 30 '15 at 07:42
  • Be aware that "return to the pool" can be different than an actually closed connection: The actual connection might sit idle in the pool, waiting to be reused by someone else. This would result in the netstat result that you're seeing – Olaf Kock Nov 30 '15 at 08:35

1 Answers1

1

Right after my last comment I'm suspecting that your code might call your util's setExpire method. Note that this is the only one where you allocate a resource but only close it in case of an exception, not in a finally block.

Try changing your implementation

@Override
public void setExpire(
                String key,
                int expireTime) {
    Jedis jedis = pool.getResource();
    try {
        jedis.expire(key, expireTime);
    } catch (Exception e) {
        jedis.close();
    }
}

to

@Override
public void setExpire(
                String key,
                int expireTime) {
    Jedis jedis = pool.getResource();
    try {
        jedis.expire(key, expireTime);
    } finally {
        jedis.close();
    }
}
Olaf Kock
  • 46,930
  • 8
  • 59
  • 90
  • Ohh..... this code is the result that make my redis resource not return maybe.let me change the impl and try again. Thanks a lot – BeeNoisy Nov 30 '15 at 09:00