Предыдущая статья: Часть 3: А при чём здесь The Thundering Herd Problem?
Часть 4: Пробуем сшить лоскутное одеяло из Dogpile и Thundering Herd
Расследование зашло в тупик. С одной стороны, у нас есть четкое, каноническое определение Dogpile Effect, подкрепленное авторитетным источником: это проблема с кешем и лавиной запросов к базе данных. С другой — рассказ лектора о репликах, которые "захлебываются" трафиком, не успев инициализироваться. А тут еще AI помощник предложил альтернативный термин Thundering Herd, спасибо ему за это огромное.
Эти два сценария не имеют между собой ничего общего. Или имеют?
Dogpile Effect — это о бесполезной нагрузке на внешний ресурс (например, БД) из-за многократного выполнения одной и той же работы.
Thundering Herd — это о бесполезной трате CPU на пробуждение "лишних" процессов, которые не смогут выполнить работу.
Хотя сегодня эти термины часто используют как синонимы, понимание этого изначального различия было важным шагом в моем "расследовании".
И это лишь усугубило мой когнитивный диссонанс. Как эта картина, где все крутится вокруг кеша, БД и пробуждения процессов, связана с новыми репликами сервиса, которые, по словам лектора, просто не успевают запуститься, как на них уже идет трафик?
На первый взгляд — никак. Но чтобы это утверждать, нужно было копнуть глубже.
Поиск авторитетного источника
Чтобы понять, кто прав, нужно было найти авторитетный источник, который бы рассудил их. И такой источник нашелся — статья "How to Avoid Cache Stampede or 'Dogpile' Problem Upon Cache Expiry?" с портала Scalable Thread (на Medium она тоже есть).
Именно эта статья и стала моим главным ориентиром в расследовании. Я решил отбросить все свои предыдущие знания и посмотреть, как проблему описывают ее авторы.
Первое и ключевое открытие: статья не противопоставляет эти термины. Наоборот, она использует их для описания одной и той же катастрофы.
В самом первом абзаце автор определяет проблему как:
"... a thundering herd problem combined with cache expiry."
(«...проблема несущегося стада, объединенная с истечением срока действия кеша»)
А уже через несколько строк, давая определение, называет ее:
"... a Cache Stampede or a Dogpile Problem."
Для автора статьи это разные названия одного и того же явления — сценария, который разворачивается, когда кеш становится недействительным в момент пиковой нагрузки.
Вот как этот сценарий описан в статье:
Система обслуживает запросы к базе данных через кеш;
В период пикового трафика срок действия кеша истекает;
Все запросы одновременно направляются в БД, чтобы получить новое значение.
Это перегружает БД, что приводит к деградации производительности всего сервиса.
Суть — неорганизованная толпа запросов атакует беззащитную базу данных.
Ускользнувшая истина
Я снова и снова перечитывал свои заметки, пока меня не осенило.
Я вспомнил как AI обратил мое внимание на белое пятно в повествовании лектора.
Все вновь созданные реплики стартуют одновременно и в первую миллисекунду своей жизни обращаются к серверу конфигурации за настройками, а затем — к базе данных, чтобы установить соединения и "прогреть" кэши.
Вместо того чтобы помочь справиться с отложенными запросами, они создают дополнительную нагрузку на БД, которая парализует ключевые части инфраструктуры.
Что это, если не Dogpile?! Картина прояснилась
Я сосредоточился на проблеме внешней координации, которую лектор описывал в сценарии отказа, который связан с разрывом между моментом создания реплики и моментом ее реальной готовности к работе и за тремя соснами не увидел проблему истощения ресурсов.
Вот пошаговый разбор того, о чем на самом деле шла речь:
Нагрузка на сервис возрастает. Метрики (CPU, RPS) превышают пороговые значения.
Система автомасштабирования (например, Autoscaler) принимает решение добавить новые реплики для распределения нагрузки и отдает команду оркестратору создать, скажем, пять новых экземпляров сервиса.
Новая реплика не готова к работе мгновенно. Ей нужно время на:
Запуск процесса приложения;
Подключение к зависимостям;
“Прогрев” внутренних кешей;
Выполнение любых других стартовых процедур.
Этот период может занимать от нескольких секунд до минуты. В это время реплика существует, но не готова обрабатывать трафик. Именно здесь начинает проявляться пресловутый Dogpile, когда куча новых реплик накидывается на БД.
Преждевременное включение в балансировку: Вот он, ключевой момент сбоя. Балансировщик нагрузки (или Service Discovery) видит, что новые экземпляры появились (они зарегистрированы, процесс запущен) и, не дожидаясь сигнала о полной готовности, начинает направлять на них часть реального пользовательского трафика.
Еще не готовые реплики получают шквал запросов, которые не могут обработать и отвечают ошибками (например, 503 Service Unavailable) либо просто падают.
Положительная обратная связь и каскадный сбой:
Общий уровень ошибок сервиса резко возрастает;
Нагрузка на оставшиеся “живые” реплики не снижается или даже увеличивается;
Система мониторинга и автомасштабирования видит, что ситуация не улучшилась (или даже ухудшилась), и может принять решение…
... создать еще больше реплик, усугубляя проблему и загоняя сервис в штопор.
Лектор использовал термин Dogpile абсолютно по делу. Он применил этот известный анти-паттерн к другой предметной области — не к данным приложения, а к его инфраструктуре.
Новые реплики, подобно пользовательским запросам, создают “кучу-малу” из реплик, рвущихся к общим ресурсам, необходимым для их инициализации.
Это открытие было для меня настоящим прорывом. Я не просто узнал определение термина, я увидел его универсальную природу. Это был тот самый момент, когда разрозненные фрагменты знаний соединяются в цельную картину.
Но оставался еще один вопрос: откуда тогда взялся Thundering Herd и почему AI-ассистент так уверенно использовал именно его? Эту часть головоломки ещё предстояло найти.
AI помощник оказался вдруг и не друг, и не враг, а — так?
Если Dogpile Effect — это точный и корректный термин для описания проблемы, с которой мы столкнулись, то почему же AI-ассистент, опираясь на авторитетные источники, так настойчиво предложил Thundering Herd? Я не сразу осознал логику AI-ассистента.
Для него, как для машины, оба сценария структурно похожи. В современном IT-дискурсе, особенно в блогах и на конференциях, эти тонкие академические различия часто стираются, и оба термина используются для описания общего феномена "лавинообразной конкуренции".
AI увидел разрушительные последствия неконтролируемой одновременности, а именно проблему внешней координации, когда Autoscaler создает "стадо" новых реплик, которые одновременно запускаются, но не способны включиться в процесс по причине наивной реализации scale-out и поэтому выбрал самый подходящий фундаментальный термин, описывающий подобное поведение и не ошибся использовав паттерн Thundering Herd.
В одну единицу времени нужна всего лишь одна "здоровая" реплика, которой нужно дать время на инициализацию и прогрев кеша, т.е. дождаться от нее сообщения о готовности.
Мое расследование привело меня к важному выводу: Я не просто выяснил, кто прав.
Я понял, что у одной и той же проблемы есть история и разные уровни проявления.
Конфликт терминов оказался на самом деле уроком по истории и архитектуре вычислительных систем. Теперь, когда теория была полностью ясна, оставалось самое главное — понять, как со всем этим бороться на практике, но об этом в следующей части.