В этот статье мы поделимся некоторыми результатами тестирования производительности Valkey (BSD-клон Redis).

В этом году Redis, “кеш с персистентностью”, мимикрирующий под СУБД и даже умеющий работать в режиме распределенного кластера – фантастически успешный проект, да и просто пример отличного продукта – сменил лицензию. Подробное рассмотрение лицензионной политики, включающее разбор лицензий Open Source и Source Available - выходит за рамки этой статьи. Скажем лишь, что это всё продолжение битвы “против облачных провайдеров”, которые “пользуются” результатами “настоящих” open source проектов, предоставляя услуги management service.

Итак, Redis cменил лицензию, и почти сразу же сотрудники AWS (Amazon Web Services, крупнейшего облачного провайдера) в сотрудничестве с другими облаками объявили о выпуске форка, Valkey: https://valkey.io/. Лицензия BSD, контроль проекта у Linux Foundation, участвуют многие контрибьюторы Redis. Major contributor проекта Valkey - Madelyn Olson (AWS Engineer and Valkey project maintainer, https://www.linkedin.com/in/madelyn-olson-valkey).

DragonFly, один из наиболее успешных коммерческих “клонов” Redis, выпустил достаточно подробный обзор отличий: https://www.dragonflydb.io/guides/valkey-vs-redis. Однако в секции про производительность там сказано странное:
▪️ Valkey: 1.19M requests per second with new I/O threading
▪️ Redis: Known for high performance but varies based on version

Цитата про миллион запросов в секунду - действительно звучала от контрибьюторов Valkey в комментарии к этим патчам: https://github.com/valkey-io/valkey/pull/861. Утверждение “known for high performance but varies based on version” кажется черезчур оценочным и малоинформативным, но мы не будет судить маркетинг DragonFly строго, он уже удивлял нас некоторыми опусами (https://habr.com/ru/articles/747814/). Так что же там с производительностью?

Disclaimer: Автор этой статьи никаким образом не связан ни с одним из упомянутых ниже проектов, не получал финансирование и не преследует никакие интересы упомянутых организаций или их конкурентов - вендоров софта либо cloud-компаний. Данный материал является краткой версией туториала образовательного облака для бекендеров - DevHands. Если вы вдруг хотите научиться самостоятельно управлять своим linux-сервером - возможно, вам будет интересен этот курс: https://devhands.ru/linux. Основная цель - дать бекендерам “альтернативый опыт управления облачными ресурсами”, который часто скрыт за интерфейсами облачных провайдеров.

Налицо два мифа. Первый: Redis не скейлится по ядрам. Второй: Valkey скейлится, или по крайней мере - скейлится лучше Redis. Постараемся разобраться, так ли это.

Поскольку Valkey - проект новый, то его пока нет ни в каких репозиториях пакетов, поэтому скорее всего придется его собрать руками. Ниже приводится пример установки на сервер с Убунтой.

Релиз-кандидат 8.0.0-rc2 лежит тут: https://github.com/valkey-io/valkey/releases. Качаем его и собираем в отдельной папке, чтобы не путаться ни с каким другими (я предпочитаю /local):

fisher@t1:/local/src$ wget https://github.com/valkey-io/valkey/archive/refs/tags/8.0.0-rc2.tar.gz

Valkey, так же как и Redis, собирается и ставится буквально несколькими командами:

fisher@t1:/local/src$ tar zxvf  valkey-8.0.0-rc2.tar.gz
...
fisher@t1:/local/src$ cd valkey-8.0.0-rc2
fisher@t1:/local/src/valkey-8.0.0-rc2$ PREFIX=/local/valkey-8.0.0-rc2 make install

Если у вас что-то не соберется - не беда, вероятнее всего, вам не хватает чего-то из сборочного тулчейна. Начните с главного пакета консольных make-джедаев build-essential:

fisher@t1:/local/src/valkey-8.0.0-rc2$ sudo apt-get install build-essential -y

Если вдруг этого будет недостаточно, по названию ошибки обычно можно понять, что не найдено, поискать через apt-cache search и поставить соответствующий пакет.

Итак, наш valkey собран, по умполчанию он создает только бинари и redis-симлинки для полной совместимости:

fisher@t1:/local$ ls -la /local/valkey/bin/
total 30572
drwxrwxr-x 2 fisher fisher     4096 Sep  7 06:33 .
drwxrwxr-x 3 fisher fisher     4096 Sep  7 06:33 ..
lrwxrwxrwx 1 fisher fisher       16 Sep  7 06:33 redis-benchmark -> valkey-benchmark
lrwxrwxrwx 1 fisher fisher       16 Sep  7 06:33 redis-check-aof -> valkey-check-aof
lrwxrwxrwx 1 fisher fisher       16 Sep  7 06:33 redis-check-rdb -> valkey-check-rdb
lrwxrwxrwx 1 fisher fisher       10 Sep  7 06:33 redis-cli -> valkey-cli
lrwxrwxrwx 1 fisher fisher       15 Sep  7 06:33 redis-sentinel -> valkey-sentinel
lrwxrwxrwx 1 fisher fisher       13 Sep  7 06:33 redis-server -> valkey-server
-rwxr-xr-x 1 fisher fisher  6584176 Sep  7 06:33 valkey-benchmark
lrwxrwxrwx 1 fisher fisher       13 Sep  7 06:33 valkey-check-aof -> valkey-server
lrwxrwxrwx 1 fisher fisher       13 Sep  7 06:33 valkey-check-rdb -> valkey-server
-rwxr-xr-x 1 fisher fisher  7494488 Sep  7 06:33 valkey-cli
lrwxrwxrwx 1 fisher fisher       13 Sep  7 06:33 valkey-sentinel -> valkey-server
-rwxr-xr-x 1 fisher fisher 17214392 Sep  7 06:33 valkey-server

Я предпочитаю такую структуру redis и valkey, в которой абсолютно все "артефакты" - от конфигурации и data-файлов до pid-файла и логов лежат вместе:

fisher@t1:/local$ ls -la valkey/
total 28
drwxrwxr-x  7 fisher fisher 4096 Aug 23 11:37 .
drwxr-xr-x  6 fisher root   4096 Sep  7 06:34 ..
drwxrwxr-x  2 fisher fisher 4096 Sep  7 06:34 bin
drwxrwxr-x  2 fisher fisher 4096 Sep  7 06:34 conf
drwxrwxr-x 26 fisher fisher 4096 Sep  7 06:34 lib
drwxrwxr-x  2 fisher fisher 4096 Sep  7 06:34 log
drwxr-xr-x  2 root   root   4096 Sep  7 06:34 run

Если будете делать так же - убедитесь, что поправили конфигурационный файл redis. Он не копируется при make install, но остается лежать в корне директории с сорцами:

fisher@t1:/local$ ls -la /local/src/valkey-8.0.0-rc2/valkey.conf
-rw-rw-r-- 1 fisher fisher 112839 Sep  3 16:00 /local/src/valkey-8.0.0-rc2/valkey.conf

Давайте запустим valkey и убедимся что он работает:

sudo /local/valkey/bin/redis-server /local/redis/conf/valkey-7023.conf

Я намеренно для простоты запускаю его под рутом на тестовой машине, в обычном окружении вам конечно нужно сделать отдельного юзера valkey/redis, сделать его owner'ом всех файлов, куда может вестись запись (данные, логи, pid-файл), и завести systemd unit-файл.

Проверяем через INFO:

fisher@t1:/local/valkey$ ./bin/valkey-cli -p 7023
127.0.0.1:7023> INFO keyspace
# Keyspace
db0:keys=0,expires=0,avg_ttl=0

Всё работает, можно приступать в тестированию. Здесь нужно сделать несколько важных замечаний.
▪️ Чтобы не перегружать читателя, мы намеренно не приводим такие данные с тестируемой машины, как CPU usage, load average и т.д. Valkey, насколько это известно, не делал большого количества оптимизаций, поэтому никакой принципиальной разницы по потреблению ресурсов в тестах замечено не было. В общем случае, или при сравнении, например с альтернативными решениями типа DragonFly или KeyDB - учёт использования ресурсов процессора, конечно, необходим.
▪️ Чтобы не тестировать дисковую подсистему, во всех тестируемых кейсах была полностью выключена персистентность: ни Redis, ни Valkey никакие данные не писали на диск - ни в режиме снэпшотирования, ни в режиме aof-лога.
▪️ Стрельбы проводились локально. Машина, на которой проводилось тестирование, железный сервер Xeon Gold 24/48 vCPU и 128G памяти - его "за глаза" хватало при том количестве как тредов стрелялки, так и тредов

Внутри у Redis есть утилита для нагрузочного тестирования, redis-benchmark, которая очень много чего умеет: открыть много соединений, пошерить их между несколькими тредами. Чего она не умеет - это ограничивать поток RPS, поэтому построить максимально информативные latency-throughput диаграммы мы не сможем, но сейчас нам это и не требуется.

Сначала запустим "стрелялку" на однопоточный valkey:

 /local/redis/bin/redis-benchmark -r 10000 -c 64 --threads 8 -p 7023 -t set -n 10000000 -d 64
(...)
Summary:
  throughput summary: 181785.14 requests per second
  latency summary (msec):
          avg       min       p50       p95       p99       max
        0.332     0.016     0.303     0.559     0.631     2.191

В этом тесте мы запускаем 8 тредов "стрелялки", которые шеряд тежду собой 64 соединения с valkey (порт 7023). Выполняется 10 миллионов операций set с 10000 ключей, каждый из которых имеет размер 64 байта. Результирущая пропускная способность составляет 181785 запросов в секунду, с 95-м перцентилем менше 1й милисекунды (0.559 msec).

Включим мульти-тредовый режим. Для этого в конфигурационном файле нужно поставить какое-то осмысленное значение для параметра io-threads, мы поставим 8:

io-threads 8

Перезапустим valkey и снова "натравим" benchmark:

fisher@t1:/local/redis$ /local/redis/bin/redis-benchmark -r 10000 -c 64 --threads 8 -p 7023 -t set -n 10000000 -d 64
(...)
Summary:
  throughput summary: 850267.88 requests per second
  latency summary (msec):
          avg       min       p50       p95       p99       max
        0.056     0.008     0.055     0.071     0.103     1.183

Почти миллион set в секунду, вполне достойно!

На get-операциях получаем вожделеннный миллион RPS:

Summary:
  throughput summary: 1024590.12 requests per second
  latency summary (msec):
          avg       min       p50       p95       p99       max
        0.050     0.008     0.055     0.063     0.079     1.911

Отличный результат. А что же Redis? Тут важно сказать, что io-threads и поддержка мульти-тредового io появилась как раз у Redis, команда Valkey её усовершенсововала. Вам может показаться это странным, но Redis скейлится по ядрам! Покажем это.

Redis на чтение в режиме одного ядра:

/local/redis/bin/redis-benchmark -r 10000 -c 64 --threads 8 -p 7022 -t get -n 10000000 -d 64
Summary:
  throughput summary: 190839.69 requests per second
  latency summary (msec):
          avg       min       p50       p95       p99       max
        0.317     0.016     0.287     0.551     0.599     2.175

Обратите внимание, в однопоточном режиме redis не valkey, даже наоборот. Потестим мульти-тредовый io (те же 8 ядер):

/local/redis/bin/redis-benchmark -r 10000 -c 64 --threads 8 -p 7022 -t set -n 10000000 -d 64
Summary:
  throughput summary: 408096.66 requests per second
  latency summary (msec):
          avg       min       p50       p95       p99       max
        0.130     0.016     0.135     0.167     0.207     1.911

Как видите, скейлится, но заметно хуже!

Итак, какие выводы можно сделать из этого небольшого исследования?

▪️ Первое, Redis таки скелится по ядрам, пусть и не очень хорошо. Примерно вдвое производительность Redis можно увеличить, подбирая оптимальный io-threads.
▪️ Второе, Valkey действительно усовершенствовали много-тредовый режим Redis, и мы увидели двойной прирост RPS при одном и том же количестве тредов (8).

Здесь нужно сказать, что вообще сильное увеличение параметра io-threads ни у Valkey, ни у Redis, не только не приводит к увеличению пропускной способности, но наоборот значительно её снижает. Связано это с тем, что треды начинают излишне конкурировать между собой, и оверхэд на мульти-тредовый режим оказывается значительно сильнее. Ну и напомним, что вообще мульти-тредовый режим в Redis/Valkey потому и называется io-threading поскольку не распаралелливает всю цепочку выполнения запросов, так что в действие вступает закон Амдала.

Напоследок можно порассуждать о кластерном режиме Redis. Действительно, у Redis есть отличный кластерный режим, в котором можно поднять несколько экземпляров на одном хосте. Кластер без реплик заводится и скейлится по ядрам процессора лучше, чем в мутильтитредовом режим - это мы проверяли. Похоже, для пользователей Redis это пока единственный способ утилизировать ядра по-настоящему мощных машин максимальным образом. Но кластер делает много чего. Поэтому сравнение с "настоящим" in-memory кешом (без персистентности) можно было бы сделать, например, поставив число реплик в 0, и направив aof в /dev/null (я кстати не проверял - сработает ли последний такой трюк, в противном случае set будет приводить к значительной дисковой активности, и честного теста не получится).Подробное тестирование производительности кластера мы делаем на практических занятиях и оно выходит за рамки этой статьи.

Комментарии и замечания к этой статье и к методике тестирования, и по идеям для дальнейшего тестирования - горячо приветствуются. ТГ-канал автора: https://t.me/rybakalexey.

Комментарии (0)