Thundering herd problem: что это и как его избежать

6 минут чтения
Средний рейтинг статьи — 4.8

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

Например:

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

Это называется thundering herd problem — «эффект стада».

Проблема опасна тем, что сама система создаёт лавинообразную нагрузку и усиливает деградацию.

Как возникает thundering herd

Обычно сценарий выглядит так:

  1. Есть общий ресурс
  2. Множество клиентов его ждут
  3. Ресурс становится доступен
  4. Все одновременно пытаются его использовать

В этот момент:

  • резко растёт нагрузка
  • появляются очереди
  • увеличивается latency
  • возможен полный отказ сервиса

Простой пример

Представим API с кэшированием.

Пока данные лежат в кэше:

  • запросы быстрые

Но TTL истёк.

Тогда:

  • сотни запросов одновременно идут в базу
  • база получает резкий spike нагрузки
  • latency растёт для всех

Это классический cache stampede — одна из форм thundering herd problem.

Где встречается эта проблема

Сетевые серверы — accept() в многопоточных серверах, массовые reconnect после сбоя.

Кэширование — одновременная регенерация данных, истечение TTL.

Распределённые системы — после восстановления сервиса клиенты начинают одновременно делать retry.

Очереди и блокировки — если множество потоков ждут mutex или event, после разблокировки они просыпаются одновременно.

Проблема в том, что нагрузка становится нелинейной: сервис уже работает медленно, клиенты начинают retry, retry создают ещё большую нагрузку, и система деградирует ещё сильнее. Так может возникнуть cascading failure.

Thundering herd в Linux и cache stampede

Исторически проблема была известна в сетевом стеке Linux: несколько процессов ждут accept(), приходит одно соединение, ядро будит сразу всех. В итоге только один процесс получает соединение, остальные просыпаются зря, происходят лишние context switch. Позже ядро Linux стало уменьшать этот эффект.

В кэшировании это превращается в cache stampede: популярный объект исчез из кэша, тысячи запросов одновременно идут пересчитывать данные. Это может перегрузить базу, обрушить backend, резко увеличить latency.

Похожий сценарий — retry storm: база отвечает медленно, API начинает отдавать timeout, клиенты делают мгновенный retry. Нагрузка удваивается, база деградирует ещё сильнее. Поэтому retry без backoff — опасная практика.

Как избежать thundering herd

Jitter для TTL. Не давайте всем объектам истекать одновременно — например, TTL = 300 ± случайное отклонение. Это распределяет нагрузку по времени.

Request coalescing. Если данные уже пересчитываются, остальные запросы ждут результат, а не запускают пересчёт заново.

Exponential backoff. При retry задержка должна увеличиваться, иначе клиенты создадут шторм запросов.

Rate limiting помогает сгладить пики нагрузки.

Circuit breaker. Если downstream-сервис деградирует, часть запросов временно блокируется. Это предотвращает лавинообразную перегрузку.

Warm-up кэша. После рестарта кэш можно прогреть заранее, чтобы избежать одновременной генерации данных.

На практике: никогда не делайте retry без backoff, используйте случайный jitter, не допускайте одновременного истечения кэша, ограничивайте fan-out запросов и следите за p95/p99 latency.

Итог

Thundering herd problem — это ситуация, когда множество клиентов или процессов одновременно создают лавинообразную нагрузку на систему.

Чаще всего проблема появляется:

  • при retry
  • в кэшировании
  • в распределённых системах
  • при восстановлении после сбоев

Если не контролировать такие сценарии:

  • latency резко растёт
  • появляются cascading failure
  • система может полностью деградировать

Поэтому защита от thundering herd — важная часть проектирования high-load сервисов.

6 минут чтения
Средний рейтинг статьи — 4.8

Настроить мониторинг за 30 секунд

Надежные оповещения о даунтаймах. Без ложных срабатываний