Распаковывая Valkey или миллион RPS на BSD-клоне Redis

от автора

В этот статье мы поделимся некоторыми результатами тестирования производительности 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.


ссылка на оригинал статьи https://habr.com/ru/articles/841912/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *