Jedis getResource() отнимает много времени

Я пытаюсь использовать Sidinal Redis, чтобы получить / установить ключи от Redis. Я пытался провести стресс-тестирование моей установки с около 2000 одновременных запросов.

Я использовал Sentinel, чтобы поставить один ключ на Redis, а затем я выполнил 1000 одновременных запросов на получение от Redis.

Но базовые джедаи, используемые моим стражем, блокируют вызов 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

Может кто-нибудь помочь отладить дальше в проблему?

1 ответ

Из реализации JedisSentinelPool getResource() из источников Jedis (2.6.2):

@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), это означает, что он пытается случайным образом получить ресурс jedis из пула, который действительно подключен к правильному мастеру, и повторяет попытку, если он не является хорошим. Это грязная проверка, а также блокирующий вызов.

super.getResource() Вызов относится к традиционной реализации JedisPool, которая фактически основана на Apache Commons Pool (2.0). Он многое делает для получения объекта из пула, и я думаю, что он даже восстанавливает, например, неудачные соединения. С большим количеством конфликтов в вашем пуле, как, вероятно, в вашем стресс-тесте, может потребоваться много времени, чтобы получить ресурс из пула, просто чтобы увидеть, что он не подключен к правильному мастеру, поэтому вы в конечном итоге вызываете его снова, добавление конкуренции, замедление получения ресурса и т. д.

Вы должны проверить все экземпляры джедаев в вашем пуле, чтобы увидеть, есть ли много "плохих" соединений.

Возможно, вам следует отказаться от использования общего пула для стресс-теста (создавайте только экземпляры Jedis, вручную подключенные к правильному узлу и аккуратно их закрывайте) или устанавливая несколько экземпляров, чтобы снизить стоимость поиска "грязных" непроверенных ресурсов джедаев.

Также с пулом из 500 экземпляров джедаев вы не можете эмулировать 1000 одновременных запросов, вам нужно как минимум 1000.

Другие вопросы по тегам