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.