Настройка производительности Redis, факторы, влияющие на производительность Redis

Redis

Преамбула

В предыдущей статье «Почему Redis такой быстрый» были представлены инструменты оценки производительности Redis и причины высокой производительности Redis. Подробнее см.: В этой статье мы расскажем о факторах, влияющих на производительность Redis, и о том, как повысить производительность Redis с точки зрения бизнеса.

Анализ процесса запроса от пользователя на Redis

Если взять в качестве примера наиболее распространенный кеш сценариев, процесс передачи трафика от пользователей к Redis Server выглядит следующим образом:

image

  1. Пользователь обращается к внутреннему серверу и вызывает соответствующий контроллер.
  2. Контроллер обращается к записи кеша и вызывает Redis через клиент Redis, чтобы получить запись из кеша. Если для получения объекта Jedis используется пул соединений Jedis, получите экземпляр соединения Jedis из пула соединений Jedis.
  3. Jedis использует протокол сериализации Redis (RESP) для кодирования команд во входной буфер сервера Redis.
  4. Redis Server получает команду из входного буфера и выполняет ее.
  5. После завершения выполнения результат выполнения помещается в выходной буфер.
  6. Клиент Jedis получает результат выполнения из выходного буфера и возвращает его контроллеру.
  7. Контроллер выполняет бизнес-логику, соответствующую запросу пользователя.

Как видно из приведенной выше диаграммы последовательности, запрос пользователя поступает на сервер Redis по сети через клиент Redis.

Поэтому при рассмотрении производительности Redis ее необходимо рассматривать с точки зрения клиента и сервера. С точки зрения бизнеса рациональное использование возможностей Redis более работоспособно, чем оптимизация сервера Redis, и получить хорошие результаты проще.

Далее будет представлена ​​оптимизация Redis с двух сторон: оптимизация бизнеса и оптимизация сервера.

оптимизация бизнеса

Задержка запроса локального Redis обычно составляет менее 1 мс, а задержка запроса Redis в том же центре обработки данных обычно составляет менее 5 мс. Другими словами, потери передачи по сети в 5 раз превышают фактическое время работы.

Поэтому, с точки зрения клиента, очень важно, как сократить потребление времени в сети.

Используйте пул соединений, чтобы сократить время, затрачиваемое на установление и удаление соединений.

Jedis — наиболее часто используемый клиент Redis для языка Java. Jedis поддерживает прямое соединение и пул соединений двумя способами.

Метод прямого подключения:

# 1. 生成一个Jedis对象,这个对象负责和指定Redis实例进行通信 
Jedis jedis = new Jedis("127.0.0.1", 6379); 
# 2. jedis执行set操作 
jedis.set("hello", "world"); 
# 3. jedis执行get操作 value="world" 
String value = jedis.get("hello");

Так называемое прямое соединение означает, что Jedis каждый раз будет создавать новое TCP-соединение, а затем отключать его после использования. Все мы знаем, что создание TCP-соединения проходит через три рукопожатия, а освобождение TCP-соединения — через четыре взмаха рук.Это очень трудоемкая операция по созданию и повторному использованию. Очевидно, что это неэффективный способ частого использования Redis.

Jedis также предоставляет метод пула соединений.节选自:《Redis开发和运维》

Выдержка из: «Разработка и эксплуатация Redis»
// common-pool连接池配置,这里使用默认配置
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); // 初始化Jedis连接池 
JedisPool jedisPool = new JedisPool(poolConfig, "127.0.0.1", 6379);
Jedis jedis = null; try {
  // 1. 从连接池获取jedis对象 
  jedis = jedisPool.getResource(); 
  // 2. 执行操作 
  jedis.get("hello"); 
} catch (Exception e) { 
    logger.error(e.getMessage(),e); 
} finally { 
  if (jedis != null) { 
  // 如果使用JedisPool,close操作不是关闭连接,代表归还连接池 
  jedis.close(); 
  } 
}

Используйте скрипты Pipeline или Lua, чтобы уменьшить количество запросов

Пулы соединений сокращают затраты времени на установление и отключение TCP-соединений. Кроме того, Redis предоставляет еще три способа повысить производительность за счет уменьшения количества запросов. (1) Команды для пакетных операций, такие как mget, mset и т. д. (2) конвейерный метод (3) Lua-скрипт

Метод трубопровода

Используйте redis-benchmark для сравнения конвейера (16 команд за раз) и обычных запросов на процессоре Intel(R) Xeon(R) E5520 @ 2,27 ГГц.

Случай использования трубопровода:

$ ./redis-benchmark -r 1000000 -n 2000000 -t get,set,lpush,lpop -P 16 -q
SET: 552028.75 requests per second
GET: 707463.75 requests per second
LPUSH: 767459.75 requests per second
LPOP: 770119.38 requests per second
Intel(R) Xeon(R) CPU E5520 @ 2.27GHz (without pipelining)

Без трубопровода:

$ ./redis-benchmark -r 1000000 -n 2000000 -t get,set,lpush,lpop -q
SET: 122556.53 requests per second
GET: 123601.76 requests per second
LPUSH: 136752.14 requests per second
LPOP: 132424.03 requests per second

Из результатов тестов видно, что использование конвейерной технологии повышает производительность примерно в 5-10 раз по сравнению с ее отсутствием.

Jedis поддерживает функцию Pipeline. Мы знаем, что Redis предоставляет методы mget и mset, но не предоставляет метод mdel. Если вы хотите реализовать эту функцию, вы можете использовать Pipeline для имитации пакетного удаления. Хотя это не атомарная команда как mget и mset, но может использоваться в большинстве сценариев.

public void mdel(List<String> keys) { 
  Jedis jedis = new Jedis("127.0.0.1"); 
  // 1)生成pipeline对象 Pipe   
  line pipeline = jedis.pipelined(); 
  // 2)pipeline执行命令,注意此时命令并未真正执行 
  for (String key : keys) { 
      pipeline.del(key);
  }
  // 3)执行命令 
  pipeline.sync(); 
}

Чтобы инкапсулировать команду del в конвейер, вы можете вызвать pipe.del (ключ String), и в это время команда выполняться не будет.

Используйте pipe.sync() для завершения вызова объекта конвейера.

В дополнение к pipe.sync() вы также можете использовать pipe.syncAndReturnAll() для возврата команды конвейера.

Причина, по которой конвейер повышает производительность

Одной из причин повышения производительности конвейера является сокращение общего времени RTT (задержка приема-передачи) команды, а с другой стороны, уменьшение общего количества системных вызовов.

RTT (время приема-передачи): задержка приема-передачи. Это важный показатель производительности в компьютерных сетях, показывающий общую задержку с момента, когда отправитель отправляет данные, до тех пор, пока отправитель не получит подтверждение от получателя (получатель отправляет подтверждение сразу после получения данных). Задержка приема-передачи (RTT) определяется тремя компонентами: временем распространения канала, временем обработки конечных систем и временем постановки в очередь и обработки в кэше маршрутизатора. Среди них значения первых двух частей относительно фиксированы в качестве TCP-соединения, а время постановки в очередь и время обработки в кэше маршрутизатора будет меняться с изменением степени загруженности всей сети. Следовательно, изменение RTT в определенной степени отражает изменение степени загруженности сети. Проще говоря, это время, которое проходит отправитель с момента отправки данных до получения подтверждения от получателя.

Разница между конвейером и скриптом lua

Redis изначально поддерживает язык Lua и предоставляет команды для выполнения сценариев lua через клиент.

Redis Lua脚本相关命令脑图

Например, мы можем использовать сценарии Lua для реализации распределенных блокировок в более ранних версиях Redis.

local current current = redis.call('incr',KEYS[1]) 

if tonumber(current) == 1 
then 
redis.call('expire',KEYS[1], ARGV[1]) 
end 

return current

При вызове команды EVAL могут передаваться неопределенные значения KEY и ARGS, доступ к этим значениям возможен через KEY[i] и ARGV[i] к соответствующим входным параметрам, а результат выполнения возвращается через return.

Другие сценарии Lua будут представлены в других статьях.

Вы можете следить за общедоступной учетной записью WeChat: нетипичный научный мужчина, просматривать список всех статей и читать статьи, связанные со сценариями Lua.

сравнение конвейера и Lua:

(1) Возвращаемые результаты разные: конвейер вернет все результаты выполнения команды, а lua-скрипт возвращает только один результат.

(2) Различные сценарии использования: сценарии lua могут выполнять сложные логические операции и предоставлять функцию кэширования сценариев для повышения производительности, как и собственные команды. Поэтому lua-скрипты можно использовать в сценариях, где логика обработки сложная, и нет необходимости возвращать или только возвращать результат операции. Конвейер используется в сценариях, где команды объединяются, чтобы уменьшить нагрузку на выполнение и перераспределить нагрузку на сервер.

Есть несколько предостережений при использовании конвейеров:

(1) Хотя нет четкого ограничения на количество команд выполнения для команд выполнения конвейера, рекомендуется ограничить количество команд выполнения. Чрезмерное количество выполняемых команд с одной стороны занимает пропускную способность сети, а с другой блокирует работу клиента.

Факторы производительности Redis Server

Производительность Redis Server в основном зависит от оборудования, распределения данных и конфигурации.

аппаратный фактор

Redis любит следующие аппаратные условия:

  1. Сеть с высокой пропускной способностью и малой задержкой. Пропускная способность сети и задержка обычно являются самыми большими недостатками производительности Redis. Поэтому необходимо выбирать сеть с высокой пропускной способностью и малой задержкой.
  2. Большой кэш, быстрый процессор: не многоядерный. В этом случае рекомендуется ЦП Intel. Процессоры AMD могут иметь вдвое меньшую производительность, чем процессоры Intel (при сравнении платформ Nehalem EP/Westmere EP/Sandy). При прочих равных условиях CPU становится ограничивающим фактором для redis-benchmark.
  3. Память и пропускная способность особенно важны при хранении больших объектов (> 10 КБ). Но еще важнее оптимизировать хранение больших объектов.
  4. Беги Redis на физической машине: redis будет медленно на виртуальной машине. Виртуализация будет иметь дополнительное потребление для обычных операций, а Redis не будет иметь слишком много накладных расходов для системных вызовов и сетевых терминалов. Рекомендуется запустить Redis на физической машине.

Влияние большой ценности

Размер пакета влияет на соответствующую скорость Redis. Когда пакет сетевых данных Ethernet меньше 1500 байт, упаковка нескольких команд в конвейерную обработку может значительно повысить эффективность. На самом деле при обработке запросов на 10 байт, 100 байт и 1000 байт пропускная способность одинакова, подробнее см. рисунок ниже.

不同数据包大小下的并发量

Поэтому, когда существует большое значение (> 10k), его следует оптимизировать во времени.

Справочная документация:

  1. Redis Benchmark

  2. Коллекция команд Redis

Что такое архитектурный дизайн? Архитектурный дизайн достаточно прочитать эту статью

Почему Redis такой быстрый?

Heavy: интерпретация последнего экологического отчета JVM за 2020 г.

BIO, NIO, AIO Резюме

Что вы знаете о новых возможностях JDK8?

Ответьте на «данные» и получите эксклюзивные технические данные, составленные наизусть бесплатно!image