awesome-everything EN
↑ Обратно к восхождению

Кеширование

Что такое cache stampede и почему он делает всё хуже

Суть Одно истечение TTL под параллельным трафиком заставляет все ожидающие запросы одновременно перестраивать кеш, превращая кеш в оружие против собственной БД.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на junior-высоте — поверхность
◷ 10 min

Flash sale стартует в полдень. Главная страница закешировалась 30 секунд назад. В 12:00:30 TTL срабатывает — и 10 000 покупателей бьют в БД одновременно. Кеш должен был это предотвратить.

Форма сбоя

Кеш-слой работает, поглощая повторяющиеся чтения. Пока ключ живой, каждый запрос возвращается за микросекунды, не касаясь БД. Уязвимость проявляется на истечении TTL: в момент, когда ключ устаревает, каждый параллельный запрос видит промах одновременно.

При низком трафике это не страшно — один запрос промахивается, перестраивает, сохраняет новое значение, следующий запрос попадает в кеш. При высоком трафике граница TTL уничтожается. Все N параллельных запросов попадают в промежуток между моментом истечения ключа и моментом, когда любой из них запишет новое значение. Каждый из них независимо запускает rebuild. БД — которую кеш прятал — теперь получает N параллельных запросов.

ФазаСостояние кешаНагрузка на БД
Нормальная работа (60-секундное окно)Ключ живой, TTL > 0Близко к нулю
Момент истеченияКлюч истёкN параллельных rebuild-запросов
После первого rebuildКлюч живой сноваБлизко к нулю

Общее число пользовательских запросов невелико — кеш поглощал их 60 с. Но пиковая параллельность на истечении равна полной нефильтрованной ставке трафика в эту одну секунду. БД была рассчитана на steady-state за кешем, а не на односекундный бёрст у потолка трафика.

Почему длинный TTL не помогает

Интуитивный фикс — «установить длинный TTL». Это не лечит stampede, только переносит его. TTL=1 час означает, что стадо приходит раз в час вместо раза в минуту. Каждый часовой stampede тяжелее, потому что больше cache-writes накапливается за одним истечением. Правильный фикс меняет то, что происходит на истечении, а не когда оно происходит.

Взрывная форма трафика — сама по себе проблема

Без кеша БД видит стабильные 5 000 RPS. С кешем и TTL=60 с БД видит почти 0 RPS 59 секунд, затем 5 000 RPS за одну секунду. Общая работа намного меньше — но пик идентичен работе без кеша. Кеш переформирует трафик из ровного в взрывной, и именно бёрст, а не объём, вызывает сбои.

Конкретный таймлайн

  1. T=0 с — homepage:v1 закеширована с TTL=60 с. Трафик: 5 000 RPS.
  2. T=0–59.9 с — cache hits. БД видит ~10 QPS (проверки здоровья).
  3. T=60.0 с — ключ истекает.
  4. T=60.0–60.4 с — 2 000 запросов приходят (5 000 RPS × 0.4 с = время rebuild). Каждый делает GET homepage:v1, получает nil, запускает 400-мс rebuild. 2 000 параллельных запросов к БД.
  5. T=60.4 с — все 2 000 rebuild завершаются. Каждый пишет новое значение. CPU БД падает.
  6. T=60.4–120.0 с — снова cache hits. Цикл повторяется в T=120.
Викторина

Что запускает cache stampede?

Викторина

Почему увеличение TTL с 60 с до 1 часа не лечит stampede?

Расставь шаги по порядку

Поставь события cache stampede в порядок:

  1. 1 Горячий ключ кеша имеет TTL=60 с и получает 5 000 RPS чтения
  2. 2 Приходит секунда 60: ключ истекает
  3. 3 5 000 параллельных запросов в следующую секунду видят cache miss
  4. 4 Все 5 000 независимо запускают один и тот же дорогой rebuild
  5. 5 CPU БД насыщается на 100%; рендеры в очереди, затем таймаут
  6. 6 Половина успевает записать новое значение; другая половина возвращает ошибку клиенту
  7. 7 Следующие 60 с кеш поглощает трафик нормально — до следующего истечения
Закончи аналогию

Заполни пропуск: cache stampede происходит, потому что много запросов промахиваются _______, все в один и тот же момент.

Вспомните перед уходом
  1. 01
    Почему кеш делает режим сбоя хуже, чем вообще без кеша, даже когда общий объём запросов ниже?
  2. 02
    Главная страница с TTL=60 с получает 2 000 параллельных запросов в секунду. Rebuild занимает 400 мс. Сколько параллельных запросов к БД производит stampede?
Итог

Cache stampede — не падение сервера и не мис-конфигурация: это нормальный механизм TTL в комбинации с параллельным трафиком. Когда горячий ключ истекает, каждый запрос в полёте видит промах и независимо запускает rebuild. БД, рассчитанная на кешированный steady-state, получает односекундный бёрст, равный полной нефильтрованной ставке трафика. Увеличение TTL только переносит бёрст во времени; оно не предотвращает его. Следующий урок покрывает две простейшие митигации: распределённый лок и in-process single-flight.

Связанные уроки
встречается в178
Продолжить восхождение ↑Лок и single-flight: ограничение параллельных rebuild
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.