Как стать автором
Обновить

Нужен ли нам сейчас кеш-слой перед СУБД

Уровень сложностиСредний
Время на прочтение13 мин
Количество просмотров26K
Всего голосов 91: ↑88 и ↓3+95
Комментарии50

Комментарии 50

Зря опустили отдельное семейство кэшей -- кэш, который находится в адресном пространстве приложения. Нет сетевых задержек, можно исключить накладные расходы на [де]сериализацию (и, как следствие, нагрузку на систему распределения памяти), масштабируемость при правильной реализации близка к теоретически максимальной, возможно применение более эффективных алгоритмов приёмки и вытеснения чем LRU/LFU.

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

Всё-таки это совсем в другой класс, и там конечно можно налопатить на порядок (или на порядки) больше RPS/thoughput.

Вопрос стоял именно в том, чтобы взять кеш-сервисы как обвязку базам, и посмотреть, как современные версии традиционных баз справляются с такой нагрузкой.

Алексей, как вам lighting, lmdb?

Не было мультитредовых бенчмарков с ним...?

В новый дотнет завезли концепцию HybridCache. Ну, то есть понятно, что идея, в общем-то лежит на поверхности, но готовая обвязка это всегда хорошо.

Довольно странная статья. На мой взгляд, вопрос в заголовке в целом сомнителен и имеет смысл в каком-то достаточно узком круге проблем. Кеш решает гораздо больше проблем. Например, сам запрос может выполняться чуть дольше по времени, чем клиент способен ждать и вы просто не решите эту проблему никак, хоть заскейлитесь. Другая часть проблем давно и успешно решается горизонтальным масштабированием, причем, там сразу ещё решается проблема отказоустойчивости.

Например, сам запрос может выполняться чуть дольше по времени, чем клиент способен ждать и вы просто не решите эту проблему никак, хоть заскейлитесь

И как кэш решает эту "проблему"?

Всё зависит сильно от задачи. В каких-то случаях может быть позволительно считать данные или их часть в фоне и класть данные в кэш и пользовательскими запросами ходить в него, например. А может и вовсе какие-то запросы могут быть предварительно прогреты для целых групп пользователей.

Вообще-то это делается не так, если у вас какие-то запросы к БД длительностью в минуты (что абсурдно), или большие вычисления, или асинхронные иные операции. Пользователь оставляет запрос на получение результата, и когда результат готов, он или посылается ему чем-то типа вебсокета, либо кладется в БД в таблицу сообщений пользователям. Но кэшу в данной задаче места не видно.

Ну вот оставьте начало задачи с текущим выполнением запроса за минуты и добавьте туда требование бизнеса показать результат за пары секунд. И вскоре вы обмажетесь кэшами, дублированием данных в более приспособленных бд, промежуточными подсчетами, хайперлоглогами и прочим добром)

или её ручная реализация с пересчётом по job'у или событию

Так именно об этом я и писал в ветке

Разработчики распределенных дб, таких как Cassandra и CockroachDB в своих книгах так и советуют делать. В мире где уже во всю пашут распределенных дб. Вопрос применения кешей достаточно странный. Так как внутренние реализации этих баз уже имеют свои кеши.

Cdc подход. Распределенные дб и такое поддерживают. Так и обновлять materialized view

Хранит готовый результат запроса, очевидно. СУБД обычно этого не делают и исполняют запрос каждый раз.

Серьезно?
Системы с кэшем имеют всегда свойство - что-то с кэшем случается, система как ни в чем не бывало работает дальше
Что будет у вас если кэш решит почиститься?

Во-первых, вы используете кэш как хранилище, а не как кэш

Во-вторых, ещё и оборачиваете работу с ним нетривиальной логикой

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

Кто использует? Все в этой ветке комментариев (включая меня) говорят о том, что это именно промежуточное хранение данных для ускорения повторного доступа к данным.

Это самая тривиальная логика работы кэша: не попали - идем за данными в более медленное хранилище.

Я не очень понимаю, почему вы считаете нетривиальной базовую логику работы с кэшами (не только для БД, но и вообще любыми). Не готов судить, что "подразумевают" авторы статьи, но вот что думают по этому поводу в AWS, например - Relational Database Caching Techniques - Database Caching Strategies Using Redis

Конкретный пример - доступность в случаях отказа основного хранилища. Даже минута простоя дорого обходится.

Принимал участие в инцидентах, где без кеша не работало бы вообще ничего и достаточно долго.

По итогам проводили серию chaos тестирований, чтобы добиться работы основных сценариев при недоступности хранилища на срок до 4 часов.

Удивлен, что нет KeyDB, учитывая что протокол полностью совместим с Redis.
Ну и read-only нагрузка - достаточно специфичный вариант, не сказать что это типичная нагрузка.
Да и в целом, для read-only - горизонтальное масштабирование зарешает (например, запуск нескольких независимых инстансов redis с одинаковыми данными). Опционально можно сделать шардинг инстансов по ключам, чтобы данные не дублировать.

Леш, редис не скалируется на запись (ибо она однопоточная), и отсюда на R/W нагрузке совсем по другому себя будет вести. Редис в большинстве кейсов с приличным W будет проигрывать упомянутым СУБД с хорошим конкаренси (особенно когда они не в serializable режиме)

Ну в целом да, но при 1.000.000 RPS сколько обычно операций на запись - больше 10%? упремся ли мы в одно ядро? Довольно важно, ~100К writes-PS main thread потянет на нормальном железе, там больше будет деградации при синках на диск (будет интересно посмотреть с aof на nvme например). Ну и кластер, write-нагрузку без кластера не смасштабировать.

Ну в целом да, но при 1.000.000 RPS сколько обычно операций на запись - больше 10%

Сколько работаю, ни разу ещё не было "обычно". Это какое-то среднее по больнице, которое ничего не даёт. У каждой задачи своя специфика.

Это общие слова, сори, и кажется, мы не спорим, либо я не понимаю, о чём. О чём?

Я не утверждаю, что "кеш не нужен", и это можно прочитать в выводах. кеш гарантирует низкий лэтенси, гарантирует хороший throuphput и база – по-прежнему риск. но риск уже меньше - традиционные базы сделали хороший шаг вперед.

Да хотя бы 1% запросов на запись. Или 3%. Просто 0% это совсем сферический конь в вакууме, очень трудно придумать реальный юз кейс кроме раздачи статики.

Предельное число запросов, что на чтение что на запись порядка 100К RPS на ядро на этих xeon gold при датасете в 10 млн 256-байтных ключей, и все эти параметры, кстати, важны. Если точно - около 160K RPS. Значит, если у вас valkey и 1M RPS, то вы "почуствуете" родовую травму редиса (main thread, не "однотредовость" - строго говоря, это неверно) только если R/W ratio > 10 (грубо). 1% или 3% - скорее всего, не почуствуете. Лучше, конечно, было бы это явно промерить - да, я согласен, про это написано в специальном разделе, в ближайшее время мы это проиллюстрируем.

Не скажу насчёт редиса, а вот постгрес может подсесть прям до отмены запросов по таймауту

Тарантул не просто умный кеш, это полноценная СУБД в памяти IMDB/IMDG с ACID и кластером.

А почему не рассмотрели Dragonfly как современную альтернативу "немасштабируемому" Redis и Memcached?

Dragonfly is an in-memory data store built for modern application workloads.

Fully compatible with Redis and Memcached APIs, Dragonfly requires no code changes to adopt. Compared to legacy in-memory datastores, Dragonfly delivers 25X more throughput, higher cache hit rates with lower tail latency, and can run on up to 80% less resources for the same sized workload.


Valkey показывает примерно в 2,5 раза больший RPS по сравнению с Redis при схожих условиях. При этом, увеличение числа ядер свыше 6–8 уже не даёт существенного прироста.

Так это получается при больших нагрузках надо переходить на Valkey?? Я думал просто перелицензированный Redis.

При больших нагрузках можно переходить на redis cluster, valkey, valkey cluster, а также на альтернативы типа dragonfly и др. Что такое перелицензированный Redis?

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

Статья странная, нет понимания ни как работают современные реляционные СУБД, ни как работают k/v хранилища. Сравнивается теплое с мягким. Что характерно для современного ИТ, статью написал некий CTO. Вот так.

Странный комментарий! Нет ни понимания статьи, ни единой аргументации, просто ноль, голый вася. Что характерно для современного ИТ, комментировал некий noname. Вот так :)

Да уж понимания предмета у меня хватает. Какая аргументация Вам нужна? Объяснить отличия реляционных БД от хранилищ ключ/значение? Объяснить, почему тесты в статье не имеют смысла? Я не смогу это сделать в одном комментарии, тут десяток статей написать надо и идти от основ организации хранилищ. Используйте Redis. Упретесь в ограничения (если это произойдет), изучайте основы.

Даже сложные вещи умный человек может объяснить в двух словах. А если он объяснить этого не хочет, напускает тумана, использует заходы типа "у вас нет никакого понимания" и "уж я-то знаю", значит, либо он не очень умный, либо у него манипулятивная цель. Поверьте, ничего идти от основ организации не нужно. Неважно, чем отличаются принципы хранения данных, потому что вы не поняли ни исторический контекст создания кеш-слоя ни смысл этой статьи. И не знаете, что Redis (при всех его недостатках) используется в гигантском количестве огромных проектов.

Алексей, очень интересная статья!
Может у вас есть в общем доступе больше информации какие именно ключи вы использовали при сборке СУБД, какие параметры конфигов меняли ?

параметры в-основном стандартные: везде менялся размер буферпула и параметры пула процессов/тредов. в mysql больше было изменений, если интересно напишите мне лс в ТГ @alexeyrybak и скину вам конфиг.

Здравствуйте! А есть графики по потреблению памяти (ОЗУ) с ростом количества соединений / запросов?

К сожалению, системно это не собиралось. Памяти конечно PPC модель потребляет заметно больше, и это и есть основная причина и ограничение для постгреса в ~5000 процессов на 128-гиговой машине.

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

Но это очень серьёзная машина с более чем 700 ГБ памяти

Хм!
А сколько сейчас памяти у типичного сервера? И вообще, какой сейчас конфиг у типичного сервера для базы данных?
А то у меня на рабочей машине сейчас 256Гб. И я хочу больше - чтобы совсем в свап не лезло.

Зависит от задач и бюджетов - года три назад, я бы сказал, что у типичного сервера баз данных 512 ГиБ оперативки и 8 (16HT) ядер, сейчас скажу, что 1.5 ТиБ памяти и 32 (64HT) ядра...

Вот это более/менее соответствует моим ощущениям.
Требования софта и, самое главное, размеры данных за последние лет 10 выросли минимум на пару порядков. И такое ощущение, что аппаратная часть не успевает за аппетитами.

а где посмотреть конфиги для СУБД? проходил ли какой-то тюнинг настроек?

Да, проходил, и как ни странно больше пришлось подкручивать у MySQL. У PostgreSQL подняли только воркеров и кеши. Если интересны какие-то специфические вопросы или примеры конфигов, напишите мне в ТГ на @alexeyrybak – вышлю.

Очень странный кейс в духе: "Представим, что специализированных кэшей не существует, у нас бесконечно много денег. Вытянут ли базы данных нагрузку, если их использовать как кэш". Никакого экономического анализа целесообразности такой замены нет. Что там с latency ответов в обоих сценариях? Использовался ли pipelining для redis-like кэшей?

Просто нагрузили базу примитивными запросами, убрав и записи и репликацию.
И автор всё равно приходит к выводу: "я понимаю, что кейс странный, я бы такое использовать на продакшене не стал". Я, конечно, рад за PostgreSQL, что он не сдох, но не вижу смысла его использовать таким образом на практике.

Нет, не надо ничего придумывать. В статье показывается, что современные СУБД умеют справиться и с очень большой простой нагрузкой, выраженной в RPS, и с достаточно большим количеством одновременных соединений. И это основные причины, почему в хайлоад-проектах стали использовать кеши (но не все). Всё, больше никаких смыслов других в статье нет.

C latency всё нормально, не все графики вошли в статью. Пайплайнинг для редиса очевидно тут наоборот не нужен, поскольку это всегда искусственное "завышение" RPS в разы, а мы честно меряем отдельные запросы.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий