Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Що таке «лавина кешу» (cache stampede) і як від неї захиститися?

Лавина кешу (cache stampede, thundering herd) - популярний ключ кешу закінчується, і сотні одночасних запитів не знаходять значення, всі разом ідуть у базу й обчислюють одне й те саме. База, що спокійно працювала завдяки кешу, раптом отримує навантаження, від якого падає. А поки вона повільна, ключ ще довше не з'являється в кеші.

Захист:

1. Блокування - обчислює лише один.

$value = Cache::get('report');

if ($value === null) {
    $value = Cache::lock('report:lock', 10)->block(5, function () {
        return Cache::remember('report', now()->plus(minutes: 10), fn () => buildReport());
    });
}

Один процес обчислює, інші чекають і отримують готове значення.

2. Stale-while-revalidate - віддавати застаріле, оновлювати у фоні. У Laravel - Cache::flexible():

$stats = Cache::flexible('dashboard:stats', [300, 900], fn () => computeStats());
  • перші 300 секунд значення свіже - віддається з кешу;
  • з 300 до 900 секунд - застаріле, але прийнятне: віддається одразу, а перерахунок запускається після відправки відповіді (лише один, із блокуванням);
  • після 900 секунд - обчислюється заново синхронно.

Користувачі майже ніколи не чекають на обчислення, а база не отримує лавини.

3. Ймовірнісне дострокове оновлення - кожен запит з невеликою ймовірністю, що зростає ближче до кінця TTL, оновлює значення заздалегідь. Лише один-два запити підуть у базу до закінчення терміну.

4. Розкид TTL (jitter) - ключі, створені одночасно (наприклад, після деплою чи прогріву), отримують трохи різний термін - і не закінчуються в одну секунду.

5. Прогрів кешу - фонова задача оновлює важливі ключі за розкладом, і користувацькі запити кеш ніколи не «пропускають».

Схожа проблема - холодний старт: після очищення всього кешу (деплой, перезапуск Redis) - лавина по всіх ключах одразу. Тому cache:clear на продакшені під навантаженням - ризикована операція.

Докладніше в документації: Laravel: stale-while-revalidate

Схожі питання