37

I'm using Jedis pool to manage connections to Redis server. An example code of mine as follows:

public Set<String> getTopArticleList(int start, int end) {
    Set<String> list = null;
    Jedis j = JedisFactory.getInstance().getJedisPool().getResource();
    Pipeline pipe = j.pipelined();
    try {
        // do stuff with redis
        pipe.sync();
    } catch (JedisConnectionException jex) {
        JedisFactory.getInstance().getJedisPool().returnBrokenResource(j);
    } finally {
        JedisFactory.getInstance().getJedisPool().returnResource(j);
    }
    return list;
}

Code to create and retrieve the Jedis pool:

class JedisFactory {
    private static JedisPool jedisPool;
    public JedisFactory() {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        jedisPool = new JedisPool(
            poolConfig,
            RedisDBConfig.HOST,
            RedisDBConfig.PORT,
            RedisDBConfig.TIMEOUT,
            RedisDBConfig.PASSWORD
        );
    }

    public JedisPool getJedisPool() {
        return jedisPool;
    }

    public static JedisFactory getInstance() {
        if (instance == null) {
            instance = new JedisFactory();
        }
        return instance;
    }
 }            

The problem is that after reaching the number of limited connections, the web cannot be accessed anymore. Am I doing something wrong?

Stefan Birkner
  • 24,059
  • 12
  • 57
  • 72
ipkiss
  • 13,311
  • 33
  • 88
  • 123
  • Can you add the whole code of JedisFactory? Especially the getInstance() impl and getJedisPool()? – zenbeni Jan 20 '14 at 09:48
  • I added the complete code of JedisFactory – ipkiss Jan 20 '14 at 09:50
  • Do you use 2 or more threads? Could be a multithreading issue? – zenbeni Jan 20 '14 at 10:08
  • My app is a servlet web and of course there are multi threads. – ipkiss Jan 20 '14 at 10:36
  • 1
    Then you should protect your JedisFactory and JedisPool instance with either setting them as static final (with eager instanciation) or volatile (with double check locking - deferred instanciation). If not, each thread can make a local copy of it (for performance), the object can be instanciated twice. So it is possible that you have many JedisPool instances at runtime that just spam your redis server that does not have enough connections. – zenbeni Jan 20 '14 at 10:55
  • Also note that `Jedis.close()` will automatically call `JedisPool.returnBrokenResource()` or `JedisPool.returnResource()` for you if the `Jedis` was acquired from a `Pool`. – Jannik Jochem Nov 04 '14 at 09:24

1 Answers1

43

You haven't configured the maxTotal size of the pool, and the default value is only 8. You could change the JedisFactory constructor to:


    public JedisFactory() {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(128);
        jedisPool = new JedisPool(poolConfig, RedisDBConfig.HOST, RedisDBConfig.PORT, RedisDBConfig.TIMEOUT, RedisDBConfig.PASSWORD);
    }

Beware also of the default value of the WhenExhaustedAction (WHEN_EXHAUSTED_BLOCK), as it may not be your desired behavior.

Jedis uses Apache Commons Pool, and you can read about its parameters here: GenericObjectPool

asgs
  • 3,928
  • 6
  • 39
  • 54
Alexandre L Telles
  • 3,375
  • 29
  • 26
  • 2
    Do you have any document that mentions about JedisPoolConfig params? I tried to search but just got a list of function api with no description. For example, I want to know what "WhenExhaustedAction" does? – ipkiss Jan 21 '14 at 01:19
  • 1
    There is no setMaxActive for JedisPoolConfig. This won't even compile. – JohnMerlino Jun 13 '14 at 01:35
  • 4
    @JohnMerlino you're right, in the newest version of Jedis, they changed the commons-pool to version 2.X, so the new method is called setMaxTotal() now, will update the answer soon. – Alexandre L Telles Jun 13 '14 at 02:19