Проблема Thundering herd и анти-паттерн Retry storm

В распределенных системах встречается такая проблема как Thundering herd (перевод: грохочущее стадо) и такой анти-паттерн как Retry storm (перевод: шторм повторов). Иногда можно подумать, что это одно и то же, но это не совсем так. Давайте разберемся в деталях.

Проблема Thundering Herd

Что это? Встречается когда много клиентов реагируют на какое-то одно событие одновременно, конкурируя за общий ресурс.

Ключевые моменты

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

Примеры

  • Релиз игры Hollow Knight: Silksong привёл к падению Steam. Все ждали момента релиза и начали одновременно скачивать игру и сервера Steam-а не справились.
  • Известный артист постит видео с котиками и миллионы его фолловеров начинают его просматривать.
  • Курс акции сильно подскакивает и все торговые роботы начинают одновременно выставлять заявки на продажу.
  • Регистрация в элитный лицей онлайн открывается в 09:00 и все родители сидят на готове.
  • В системе срабатывает событие пересчета большого количества единиц данных, а на каждую единицу данных создается отдельный воркер, который делает запросы в БД, при этом ограничение на количество воркеров отсутствует.

Как решить?

  • Ограничить количество получателей сообщения. Например, информировать о событии постепенно, группами, если это возможно (открытие серверов предзагрузки по регионам, как в случае с Hollow Knight).
  • Отвязать нагрузку напрямую от сервиса, добавив очередь для обработки запросов (подход load leveling). Кажется в какой-то европейской стране при покупке билетов онлайн меня ставили в очередь на ожидание доступа к сервису, чего я нигде не встречал.
  • Иметь возможности к быстрому масштабированию ресурсов, если о событии нужно сообщить одновременно всем (как в случае с торгами или регистрацией в лицей).
  • Отказать части или даже всем клиентам на время (подходы Load shedding, Circuit Breaker или Rate Limiting, но в них пока не будем углубляться).

Анти-паттерн Retry storm

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

Ключевые моменты

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

Примеры

  • В какой-то момент нагрузка на это стороннее API постинга в соц. сети возрастает и оно начинает выдавать некоторым клиентам ошибки. Эти клиенты начинают повторять свои запросы, увеличивая нагрузку, что приводит к полному отказу в обслуживании.
  • Какой-то запрос залочил доступ к БД на долгое время, а другие клиенты начинают постоянно повторять свои отваливающиеся запросы.

Как решить?

  • Использовать кеширование на стороне клиента, если запросы на чтение.
  • Использовать механизм exponential backoff with jitter на стороне клиента. Exponential — значит что каждый следующий повтор делается с увеличивающимся интервалом. Jitter — значит, что для уменьшения количества одновременных запросов мы ещё закладываем случайное отклонение в размер интервала повтора.
  • Поскольку сервис уже испытвает проблемы, сам он не может регулирвоать нагрузку, поэтому можно перед сервисом добавить прокси или балансировщик, который будет регулировать нагрузку за счет механизмов Circuit Breaker, Rate Limiting, Load shedding. Если сервис уже испытывает проблемы, то load leveling (например, добавление очереди) скорее всего уже не спасёт.

Таким образом, Thundering herd и Retry storm часто идут рука об руку. Thundering herd может привести к частичному отказу системы, который усугубится из-за плохо реализованного механизма повторов на клиенте, который приводит к retry storm.