【问题标题】:Threads were in waiting state while getting a resource from JedisPool从 JedisPool 获取资源时线程处于等待状态
【发布时间】:2017-11-30 12:35:51
【问题描述】:

我正在使用 jedis 连接 redis 服务器。 Redis ip 值配置在单独的文件中,我正在尝试在初始化期间加载该文件

private static JedisPool pool;

public static void initRedisClient() throws Exception {
   String redisConfigPath = "/conf/redis.properties";
   Properties docsRedisProp = RedisUtils.loadProperties(redisConfigPath);
   pool = new JedisPool(docsRedisProp.getProperty("redisserver"));    
   }
}

而我的mget从redis中获取多个key的方法如下

public static List<String> mgetDataFromRedisCache(String[] keys) throws CacheException {
        Jedis jedisCon = null; 
        try {
            jedisCon = getJedis();
            jedisCon.select(1);
            return jedisCon.mget(keys);
        } catch (Exception e) {
            LOGGER.warning("Exception while fetching data from Redis Client. EXCEPTION=" + e.getMessage());
            e.printStackTrace();
        } finally {
            if (jedisCon != null) {
                returnJedis(jedisCon);
            }
        }
        return null;
    }

当我在属性文件中提供了不正确的 ip 值时 - 访问它的请求线程正在等待很长时间。我的请求不应该因为池中的资源不可用而停止。

这里我附上了停滞线程(即处于等待状态的线程)的线程转储

###_http-nio-8443-exec-140" #104908 daemon prio=5 os_prio=0 tid=0x00007f247805f000 nid=0x4266 waiting on condition [0x00007f220a4df000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000006fe438408> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
    at org.apache.commons.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:524)
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:438)
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:361)
    at redis.clients.util.Pool.getResource(Pool.java:40)
    at redis.clients.jedis.JedisPool.getResource(JedisPool.java:84)
    at com.retail.store.RedisClient.getJedis(RedisClient.java:53)
    at com.retail.store.RedisClient.mgetDataFromRedisCache(RedisClient.java:82)

我怎样才能做到这一点?任何帮助深表感谢。在此先感谢:-)

【问题讨论】:

  • 您是否发现了有关此主题的任何信息?我们在将 redis 与 spring-data-redis 一起使用时遇到了同样的问题(但也有 Jedis 作为客户端)
  • @woezelmann 设置 setMaxWaitMillis 帮助了我。在下面的回答中解释了我..请调查一下。希望有帮助!!

标签: java multithreading redis jedis


【解决方案1】:

redis 服务器 ip 维护在一个属性文件中,并在运行时加载它。

属性文件包含默认 ip。但是当我在我的开发设置中部署相同的内容时,redis ip 应该已经更改,但我错过了这样做。我的开发设置无法连接到给定的 ip。

Jedis 有以下默认配置

最大活动连接数 = 8

读取超时 = 2000

Maximum active connections 是池可以同时容纳的最大活动连接数。

read time out 是在建立连接并准备好通过已建立的连接接收数据时设置的最长时间(毫秒)。

在我们的例子中,连接没有建立(对于前 8 个线程)并且它从未被终止 - 连接是 timeout 没有为这些连接设置。使get 调用redis 的其他线程现在进入停放WAIT 状态。

通过设置以下池配置(即设置建立连接的最大等待时间),我们可以避免线程进入长时间等待状态

JedisPoolConfig jedisConfig = new JedisPoolConfig();
jedisConfig.setMaxWaitMillis(maxWaitInMillis);

【讨论】:

    【解决方案2】:

    您可以使用适当的constructor 创建具有短暂超时的绝地连接。

    Jedis jedisCon = public Jedis(String host, int port, int timeout);
    

    【讨论】:

    • 我猜默认超时值是2000毫秒..这是2秒...
    • 这 2 秒会导致线程在应用服务器中停滞吗?
    • 比如当有太多的请求到达应用服务器时——这2s会造成很大的影响——从而使请求线程停滞不前?
    • @rajasubasubramanian33 因此,导致问题的不是初始连接。您可以将日志添加到您的代码中并找到行会阻塞执行吗?
    • 是的,不是初始连接导致问题 - 请求在mget 期间停止(同时从 redis 获取多个密钥)。使用停止请求的线程转储日志编辑了问题。请调查一下..
    猜你喜欢
    • 2018-01-17
    • 2014-01-31
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多