【问题标题】:Jedis getResource() is taking lot of timeJedis getResource() 花费了很多时间
【发布时间】:2015-08-02 21:39:06
【问题描述】:

我正在尝试使用前哨 redis 从 redis 获取/设置密钥。我试图用大约 2000 个并发请求对我的设置进行压力测试。

我使用 sentinel 将单个键放在 redis 上,然后我从 redis 执行了 1000 个并发获取请求。

但是使用我的哨兵的底层绝地武士正在阻止对 getResource() 的调用(池大小为 500),我实现的总体平均响应时间约为 500 毫秒,但我的目标约为 10 毫秒。

我在这里附上 jvisualvm 快照的示例

redis.clients.jedis.JedisSentinelPool.getResource() 98.02227    4.0845232601E7 ms   4779
redis.clients.jedis.BinaryJedis.get()   1.6894469   703981.381 ms   141
org.apache.catalina.core.ApplicationFilterChain.doFilter()  0.12820946  53424.035 ms    6875
org.springframework.core.serializer.support.DeserializingConverter.convert()    0.046286926 19287.457 ms    4
redis.clients.jedis.JedisSentinelPool.returnResource()  0.04444578  18520.263 ms    4
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept()   0.035538    14808.45 ms 11430

有人可以帮助进一步调试问题吗?

【问题讨论】:

    标签: redis jedis jvisualvm spring-data-redis


    【解决方案1】:

    来自 Jedis 资源 (2.6.2) 中 getResource() 的 JedisSentinelPool 实现:

    @Override
    public Jedis getResource() {
        while (true) {
          Jedis jedis = super.getResource();
          jedis.setDataSource(this);
    
          // get a reference because it can change concurrently
          final HostAndPort master = currentHostMaster;
          final HostAndPort connection = new HostAndPort(jedis.getClient().getHost(), jedis.getClient()
              .getPort());
    
          if (master.equals(connection)) {
            // connected to the correct master
            return jedis;
          } else {
            returnBrokenResource(jedis);
          }
        }
    }
    

    注意while(true)returnBrokenResource(jedis),这意味着它会尝试从确实连接到正确master 的池中随机获取jedis 资源,如果它不是好的则重试。这是一个脏检查,也是一个阻塞调用。

    super.getResource() 调用指的是 JedisPool 传统实现,它实际上基于 Apache Commons Pool (2.0)。从池中获取对象做了很多工作,我认为它甚至可以修复失败的连接。由于您的池有很多争用,可能在您的压力测试中,从池中获取资源可能需要很长时间,只是为了看到它没有连接到正确的主服务器,所以您最终调用它再次,增加争用,减慢获取资源等...

    您应该检查池中的所有 jedis 实例,看看是否有很多“坏”连接。

    也许您应该放弃使用公共池进行压力测试(仅创建手动连接到正确节点的 Jedis 实例,并很好地关闭它们),或者设置多个以减轻寻找“脏”未检查 jedis 的成本资源。

    还有一个包含 500 个 jedis 实例的池,您无法模拟 1000 个并发查询,您至少需要 1000 个。

    【讨论】:

      猜你喜欢
      • 2017-05-10
      • 2011-06-21
      • 1970-01-01
      • 1970-01-01
      • 2016-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多