Jedis池是如何工作的?

37

我正在使用 Jedis 连接池来管理 Redis 服务器的连接。以下是我的示例代码:

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;
}

创建和检索Jedis池的代码:

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;
    }
 }            

问题在于达到了限制连接数后,无法再访问网站。我做错了什么吗?


你能添加JedisFactory的整个代码吗?特别是getInstance()实现和getJedisPool()方法? - zenbeni
我添加了JedisFactory的完整代码。 - ipkiss
你使用了2个或更多线程吗?这可能是一个多线程问题吗? - zenbeni
我的应用程序是一个Servlet Web,当然有多个线程。 - ipkiss
1
然后,您应该通过将它们设置为静态最终(使用急切实例化)或易失性(使用双重检查锁定-延迟实例化)来保护JedisFactory和JedisPool实例。如果没有这样做,每个线程都可以制作它的本地副本(以提高性能),对象可能会被实例化两次。因此,在运行时可能会有许多JedisPool实例,这些实例只是垃圾邮件您的redis服务器,而该服务器没有足够的连接。 - zenbeni
请注意,如果Jedis是从一个池中获取的,那么Jedis.close()将自动为您调用JedisPool.returnBrokenResource()JedisPool.returnResource() - Jannik Jochem
1个回答

43
你还没有配置池的 maxTotal 大小,而默认值只有 8。你可以将 JedisFactory 构造函数改为:

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

还要注意 WhenExhaustedAction(WHEN_EXHAUSTED_BLOCK)的默认值,因为它可能不是您期望的行为。
Jedis使用Apache Commons Pool,您可以在这里阅读有关其参数的信息:GenericObjectPool

2
你有没有关于JedisPoolConfig参数的文档?我试图搜索,但只得到了一个没有描述的函数API列表。例如,我想知道"WhenExhaustedAction"是什么意思? - ipkiss
1
JedisPoolConfig 中没有 setMaxActive 方法,这段代码甚至无法编译。 - JohnMerlino
4
@JohnMerlino 你是对的,在最新版的Jedis中,他们将commons-pool更改为2.X版本,所以现在新的方法叫做setMaxTotal(),我会尽快更新答案。 - Alexandre L Telles

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接