ТестированиеНагрузочное тестированиеИнженер по нагрузочному тестированию

В нагрузочном тесте после увеличения числа пользователей p95 сначала растёт, а затем неожиданно снижается п...

В нагрузочном тесте после увеличения числа пользователей p95 сначала растёт, а затем неожиданно снижается при стабильном числе ошибок. Как изменение коэффициента попаданий в кэш может объяснить такую динамику?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

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

Такой результат не доказывает улучшение общей производительности системы. Нужно отдельно проверить hit ratio, промахи кэша, нагрузку на хранилище и состав запросов: изменение профиля обращений могло сделать тест менее репрезентативным.

Исторический контекст

Кэширование появилось как способ уменьшить стоимость повторного доступа к данным и снизить нагрузку на более медленные уровни системы: базу данных, файловое хранилище или внешний сервис. Идея основана на повторном использовании недавно полученных результатов.

В нагрузочном тестировании кэш особенно важен, потому что измеряемое время может сильно зависеть от состояния кэша. Тест с прогретым кэшем и тест с пустым кэшем фактически проверяют разные режимы работы системы.

Постановка проблемы

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

Если после этого растёт доля попаданий в кэш, запросы становятся быстрее, а обращения к базе данных сокращаются. Неверный вывод будет выглядеть так: система якобы лучше масштабируется при большей нагрузке, хотя на самом деле изменилось состояние кэша или распределение ключей.

Дополнительный риск связан с нерепрезентативным тестовым набором. Маленький набор идентификаторов искусственно повышает повторяемость запросов и может дать значительно более высокий hit ratio, чем в реальном трафике.

Подробное решение

У запроса обычно есть два принципиально разных пути. При попадании в кэш система быстро возвращает сохранённый результат. При промахе она обращается к источнику данных, выполняет вычисление, а затем может сохранить результат в кэш.

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

Для проверки гипотезы нужно сопоставить во времени:

  • p50, p95 и p99 задержки;
  • коэффициент попаданий и число промахов кэша;
  • задержку и нагрузку на базу данных или другой источник данных;
  • распределение запрашиваемых ключей;
  • объём кэша, вытеснения и истечения TTL.

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

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

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

Ситуация из практики

В сервисе каталога при увеличении нагрузки p95 вырос с 180 до 420 миллисекунд, а затем через несколько минут снизился до 230 миллисекунд. Ошибки оставались на прежнем уровне.

Рассматривались три варианта:

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

Метрики показали, что hit ratio вырос с 35% до 92%, а нагрузка и задержка базы данных резко снизились. Причиной оказался слишком маленький набор идентификаторов в тестовых данных: после прогрева почти все запросы обращались к уже сохранённым объектам.

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

Что кандидаты часто упускают

  1. Может ли высокий hit ratio скрывать деградацию источника данных?

Да. Если большинство запросов обслуживается кэшем, средняя нагрузка и задержка базы данных могут выглядеть приемлемо даже при сильном ухудшении обработки промахов. Небольшая доля промахов способна определять p99, особенно если они требуют тяжёлых запросов или обращений к внешним системам.

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

  1. Почему увеличение нагрузки иногда ухудшает hit ratio, а не улучшает его?

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

К тому же увеличение нагрузки может ускорить истечение TTL относительно времени повторного обращения. Поэтому связь между нагрузкой и hit ratio не обязана быть монотонной: она зависит от размера рабочего набора, политики вытеснения, TTL и распределения популярности ключей.

  1. Достаточно ли прогреть кэш перед тестом, чтобы получить достоверный результат?

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

Нужно определить, какой режим соответствует цели теста: доля горячих данных в обычной эксплуатации, поведение после рестарта, массовое истечение TTL или работа при смене набора ключей. Иначе можно получить стабильные метрики, относящиеся к искусственно благоприятному сценарию.