Кэширование при масштабе: построй и сломай кэш
Практический проект: поставь кэш перед медленным хранилищем с выбранной стратегией, измерь hit ratio и нагрузку БД за ним, затем намеренно вызови и почини стампиду, устаревшее чтение и шторм синхронного истечения.
Прочитать, что стампида множит нагрузку БД и что удаление-на-записи гоняется — не то же, что увидеть, как твоя собственная база падает, а потом починить. Поставь реальный кэш перед намеренно медленным хранилищем, измерь hit ratio и нагрузку, что он прячет, и затем сломай его нарочно — стампида, устаревшее чтение, шторм синхронного истечения — и почини каждое техникой из раздела.
Этот проект делает весь раздел операционным: ты выберешь стратегию и докажешь математику hit ratio против измеренного числа нагрузки базы, затем воспроизведёшь три фирменных сбоя — стампиду, гонку устаревшего чтения и шторм TTL-обрыва — и продемонстрируешь, что починки раздела реально их устраняют.
Построй слой кэша перед медленным бэкенд-хранилищем, инструментируй его hit ratio и нагрузку бэкенда за ним, а затем намеренно воспроизведи и почини стампиду кэша, гонку устаревшего чтения на записи и шторм синхронного истечения (TTL-обрыв) — замыкая цикл между теорией раздела и наблюдаемым поведением.
- Работающий кэш-перед-хранилищем с живыми счётчиками попаданий, промахов и чтений бэкенда/с и залогированным стационарным hit ratio, что совпадает с измеренной нагрузкой бэкенда через backend_reads ≈ total_reads × (1 − hit_ratio).
- Воспроизведённая стампида с зафиксированным всплеском чтений бэкенда при каждом истечении горячего ключа и измерение после починки, показывающее, что single-flight схлопывает его до ~1 пересчёта на истечение.
- Воспроизведённое устаревшее чтение на записи (старое значение, отравляющее ключ после delete) и исправленная версия версионированными ключами (или TTL-подстраховкой), где устаревшее значение больше не сохраняется, продемонстрированное тестом.
- Воспроизведённый шторм синхронного истечения (периодический всплеск бэкенда на границе общего TTL) и измерение после джиттера, показывающее сглаженный всплеск.
- Краткое описание, связывающее каждый наблюдённый сбой с механизмом и починкой раздела, с числами нагрузки бэкенда до/после для всех трёх.
- Шардируй кэш по нескольким узлам и сравни модуло (hash % N) против консистентного хеширования при добавлении узла: измерь долю ключей, что промахиваются сразу после смены топологии, и покажи, что модуло массово промахивает, а консистентное хеширование тревожит лишь ~1/N.
- Добавь сценарий насыщения горячего ключа: маршрутизируй один крайне горячий ключ и покажи насыщение одного шарда, затем смягчи репликацией ключа или in-process near-кэшем и измерь перераспределение нагрузки.
- Добавь сценарий холодного старта: сбрось кэш под нагрузкой и измерь всплеск нагрузки бэкенда и время восстановления, затем сравни прогрев кэша сначала против приёма трафика холодным.
- Реализуй вероятностный ранний пересчёт (обновляй горячий ключ до истечения) и сравни его с single-flight по хвостовой задержке на границе истечения.
- 01Как доказать связь hit ratio/нагрузка БД эмпирически?
- 02Как воспроизвести и починить стампиду в нагрузочном тесте?
- 03Как продемонстрировать гонку устаревшего чтения и шторм синхронного истечения и их починки?
Этот проект превращает раздел кэширования в повторяемый процесс «построй и сломай». Сначала ты делаешь математику hit ratio реальной: ставишь кэш перед намеренно медленным хранилищем через cache-aside, инструментируешь попадания, промахи и чтения бэкенда/с и подтверждаешь измеренными числами, что backend_reads ≈ total_reads × (1 − hit_ratio) — так что падение hit ratio 99%→90% всплывает как 10× всплеск нагрузки бэкенда. Затем ты воспроизводишь и чинишь три фирменных сбоя: стампиду (истечение горячего ключа триггерит всплеск одновременных пересчётов, схлопываемый до ~1 через single-flight), гонку устаревшего чтения на записи (старое значение, записанное обратно после delete, устраняемое версионированными ключами и TTL-подстраховкой) и шторм синхронного истечения (периодический всплеск, когда равномерно-TTL-ключи истекают вместе, сглаживаемый джиттером). Каждый сбой связан с механизмом раздела и доказан починенным числами нагрузки бэкенда до/после. Стретч-цели толкают в распределение — модуло против консистентного хеширования при rescale, насыщение горячего ключа и холодный старт. Инженер, построивший это раз, перестаёт относиться к кэшу как к волшебному ускорению и начинает относиться к нему как к системе с измеримым поведением и предсказуемыми сбоями, против которых проектируешь заранее.
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.