Вход на сайт

Просмотр новости

Найдите то, что Вас интересует

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

Дата публикации: 05-08-2026 14:30:34

Некоторое время назад мне пришла задача спроектировать высокопроизводительный балансировщик нагрузки для протокола Diameter. Через 3 месяца задача исчезла, так как как оказалось слишком долго и дорого, но в итоге балансировщик был сделан и имеется его MVP которое готово к установке как на реальное железо так и в облаке. В итоге продукт получился неплохим, и он с лихвой выигрывал имееющееся решение в той компании, по производительности был выигрыш раз в 6 по ресурсам раз в 100. Но суть не в этом, а в том что балансировщик был кластерным и умел хранить сессии в Redis. Решение было сделано, оно показало работоспособность, все хорошо, но меня не устраивала производительность. В тот момент я столкнулся с очень интересной проблемой - по каким то причинам я не мог пробить барьер в 5-7К Diameter Transactions per second. В принципе 5-7К TPS было неплохо, но проблемным участком как показал анализ был Redis. Проведя немного времени я смог добиться приемлемого результать и производительность поднялась до 20К TPS но там были другие проблемы. Читать далее

Основное содержимое страницы с новостью.

Преамбула

Некоторое время назад передо мной встала задача спроектировать высокопроизводительный балансировщик нагрузки для протокола Diameter. Через три месяца проект на стороне заказчика свернули — решение показалось слишком долгим и дорогим в разработке. Тем не менее, я довел дело до конца и собрал MVP, готовый к развертыванию как на «голом железе», так и в облачной инфраструктуре.

Продукт получился отличным: он с лихвой выигрывал у имевшегося в компании решения, превосходя его по производительности примерно в 6 раз, а по эффективности использования ресурсов — почти в 100 раз.

Но речь сейчас не о самом балансировщике, а об одной из его ключевых частей. Балансировщик был кластерным и хранил сессии в Redis. Система работала, функциональность была подтверждена, но меня категорически не устраивала производительность. Я столкнулся с удручающим барьером: по непонятным на первый взгляд причинам система упиралась в 5 000–7 000 Diameter Transactions Per Second (TPS).

Профилирование показало, что узким местом был именно Redis. Потратив некоторое время на оптимизацию взаимодействия, я сумел поднять производительность балансировщика до 20 000 TPS, но это решение заставило пойти на компромиссы и принесло новые проблемы.

Причины создания HurriCache

Проведя детальный анализ, я выяснил: без пайплайнинга Redis физически не способен отдавать данные быстрее 5 000–6 000 RPS на одно соединение/поток. Мой балансировщик аккуратно подтвердил эту цифру, упершись ровно в данный потолок.

Чтобы преодолеть ограничение, я перепробовал разные подходы: от нативного пайплайнинга до группировки запросов в батчи. Желанные 20 000 TPS для балансировщика в итоге были достигнуты, и формальная цель проекта была выполнена. Однако меня зацепил исследовательский вопрос: какова реальная (а не маркетинговая) пропускная способность Redis на одной ноде?

Серия синтетических тестов дала следующие результаты:

Тип операции

Без пайплайна (Single Request)

С пайплайном (Pipelined)

Чтение

5К RPS

60К RPS

Запись

3К RPS

20К RPS

Эта таблица наглядно объясняет, почему пробить потолок в 20 000 TPS на реальной бизнес-логике балансировщика оказалось настолько сложно.

В этот момент и родилась идея: а что если спроектировать собственное in-memory хранилище — похожее на Redis по возможностям, но избавленное от его фундаментальных сетевых и архитектурных узких мест?

Так началась разработка HurriCache.

Архитектурный фундамент HurriCache

Одна из главных проблем Redis — невозможность переиспользовать сетевое соединение до тех пор, пока из него не будут полностью вычитаны данные предыдущего ответа (отсутствие честного мультиплексирования). Из-за этого использовать Redis без пулов соединений (Connection Pools) в высоконагруженных системах практически бессмысленно. Пулы частично решают проблему, но создают оверхед на менеджмент соединений и контекст-свичи.

Я решил сразу строить транспортный слой на протоколе с нативной поддержкой мультиплексирования.

В качестве фундамента был выбран gRPC + Protocol Buffers. Это дало возможность гонять тысячи параллельных запросов через одно TCP-соединение без блокировок и оверхеда на парсинг текстового протокола RESP.

Далее я спроектировал Protobuf-интерфейс, который закрывает большинство привычных примитивов Redis и добавляет то, чего в нем исторически не хватало:

  • Basic Key-Value (строки, бинарные данные);

  • Lists (массивы и связные списки);

  • Queues (очереди с гарантией порядка);

  • HashSet / HashMap;

  • OrderedSet / OrderedMap;

  • Atomics (полный набор атомарных операций, включая Compare-And-Swap / CAS);

  • Locks (поддержка READ/WRITE/GLOBAL locks в зависимости от клиента)

  • Нативная кластеризация «из коробки».

Архитектурные делемы и интересные проблемы

В процессе разработки выяснилось множество интересных деталей о поведении стандартных C++ контейнеров под экстремальной нагрузкой.

Например, популярные решения std::unordered_map и absl::flat_hashmap на моих синтетических профилях вызовов показывали практически одинаковую производительность, упираясь в промахи по кэшу процессора.

После долгой борьбы с L1/L2/L3 cache misses и тонкой настройки процессорных инструкций префетчинга (prefetch), мне пришлось написать собственную реализацию flat_hashmap, оптимизированную под специфику аллокаций HurriCache.

(Детальный разбор реализации этой хэш-таблицы, борьбы с cache miss и работы с memory arenas я планирую вынести в отдельную техническую статью, иначе этот материал получится бесконечным).

Что получилось в итоге

На текущий момент HurriCache уверенно работает в кластерном режиме. Вот реальные показатели производительности на одну ноду без ухищрений с пайплайнингом:

Тип операции

HurriCache (Без пайплайнинга)

Redis (Без пайплайнинга)

Redis (С пайплайном)

Чтение (Read)

85 000+ RPS

~5 000 RPS

~60 000 RPS

Запись (Write)

77 000+ RPS

~3 000 RPS

~20 000 RPS

Примечание: Концепция классического пайплайнинга в HurriCache просто не требуется — мультиплексирование gRPC позволяет насыщать канал асинхронными запросами без искусственной задержки на сбор батча.

Заключение

Как первое приближение и MVP, HurriCache показал себя крайне интересным и жизнеспособным решением. Нам удалось не просто догнать Redis с пайплайнингом, а превзойти его показатели (особенно на операциях записи: 77K RPS против 20K RPS), сохранив при этом прозрачность синхронного кода без необходимости собирать ручные батчи на стороне клиента.

Сейчас проект активно развивается: впереди создание клиентов на разных языках программирования. На данный момент уже реализован клиент на Java. Благодаря выбору стек-технологий gRPC + Protocol Buffers, поддержка которых есть практически везде, реализация клиентов под другие языки не должна вызывать особых сложностей.

Буду рад ответить на вопросы по архитектуре в комментариях!

Схожие новости

#Наименование новостиТональностьИнформативностьДата публикации
1Как Яндекс Диск выдерживает сотни гигабит входящего трафика: устройство балансировки загрузок18.0401-06-2026
2От полной выгрузки к S3 и PostgreSQL: как мы доставляем гигабайты данных в память подов5706-07-2026
3Valkey и Redis: два года спустя — за кем будущее?07.3222-06-2026
4Чат на сайте стоит дороже, чем кажется: как я замерил его цену и переписал виджет под результат09.5828-07-2026
5Я делал «nginx для телеграм‑ботов», а получился конструктор шлюзов на Rust09.3906-07-2026
6Считаем пакеты на Rust09.8704-07-2026
7librats: Выпуск версии 2.0.x (библиотека для распределённых P2P-приложений). Так же релиз rats-search 2.1.7 и rasync012.0203-08-2026
8Читаю на Интерфаксе статью академика РАН Арбатова, руководителя Центра международной ...09.4930-07-2026
9После установки патча 2-50 для моего движка у «умного ИИ» ...0730-07-2026
10Нулевой баланс больше не страшен: что даст россиянам проект "Доступный интернет"0008-04-2020

Классификация: . Схожих патентов: 0. Схожих новостей: 10. Тональность: 1. Информативность: 7. Источник: habr.com.