В нагрузочном тесте после увеличения числа пользователей p95 сначала растёт, а затем неожиданно снижается при стабильном числе ошибок. Как изменение коэффициента попаданий в кэш может объяснить такую динамику?
Падение p95 после его первоначального роста может быть связано с повышением коэффициента попаданий в кэш. При росте нагрузки нужные данные или вычисленные результаты начинают чаще находиться в кэше, поэтому часть запросов перестаёт обращаться к медленному хранилищу или выполнять дорогие вычисления.
Такой результат не доказывает улучшение общей производительности системы. Нужно отдельно проверить hit ratio, промахи кэша, нагрузку на хранилище и состав запросов: изменение профиля обращений могло сделать тест менее репрезентативным.
Кэширование появилось как способ уменьшить стоимость повторного доступа к данным и снизить нагрузку на более медленные уровни системы: базу данных, файловое хранилище или внешний сервис. Идея основана на повторном использовании недавно полученных результатов.
В нагрузочном тестировании кэш особенно важен, потому что измеряемое время может сильно зависеть от состояния кэша. Тест с прогретым кэшем и тест с пустым кэшем фактически проверяют разные режимы работы системы.
При увеличении числа виртуальных пользователей обычно ожидают роста конкуренции за CPU, соединения и хранилища. Однако при повторяющемся или ограниченном наборе данных нагрузка может одновременно повысить вероятность обращения к одним и тем же ключам.
Если после этого растёт доля попаданий в кэш, запросы становятся быстрее, а обращения к базе данных сокращаются. Неверный вывод будет выглядеть так: система якобы лучше масштабируется при большей нагрузке, хотя на самом деле изменилось состояние кэша или распределение ключей.
Дополнительный риск связан с нерепрезентативным тестовым набором. Маленький набор идентификаторов искусственно повышает повторяемость запросов и может дать значительно более высокий hit ratio, чем в реальном трафике.
У запроса обычно есть два принципиально разных пути. При попадании в кэш система быстро возвращает сохранённый результат. При промахе она обращается к источнику данных, выполняет вычисление, а затем может сохранить результат в кэш.
На начальном этапе теста кэш может быть холодным: промахов много, поэтому p95 высок. По мере повторения запросов популярные ключи заполняются, доля попаданий увеличивается, а дорогие операции выполняются реже. В результате p95 может снизиться даже при большем числе пользователей.
Для проверки гипотезы нужно сопоставить во времени:
Важно различать стабильный прогрев и случайное изменение поведения. Если кэш ограничен по размеру, новые ключи могут вытеснять старые. При высокой конкуренции возможен «шторм промахов»: несколько запросов одновременно не находят один ключ и независимо повторяют дорогостоящую операцию.
Сравнивать версии системы следует при одинаковом состоянии кэша и одинаковом распределении ключей. Часто полезно проводить отдельные сценарии с холодным кэшем, прогретым кэшем и реалистичным длительным потоком, где ключи появляются и вытесняются с ожидаемой частотой.
Главный компромисс таков: прогретый кэш может отражать обычную эксплуатацию, если в продакшене данные действительно долго живут и часто переиспользуются. Но он скрывает стоимость первоначальной загрузки, промахов и обновления данных, поэтому одним режимом нельзя описать всю производительность.
В сервисе каталога при увеличении нагрузки p95 вырос с 180 до 420 миллисекунд, а затем через несколько минут снизился до 230 миллисекунд. Ошибки оставались на прежнем уровне.
Рассматривались три варианта:
Метрики показали, что hit ratio вырос с 35% до 92%, а нагрузка и задержка базы данных резко снизились. Причиной оказался слишком маленький набор идентификаторов в тестовых данных: после прогрева почти все запросы обращались к уже сохранённым объектам.
Тест повторили с распределением ключей, близким к рабочему, и с отдельными измерениями холодного и прогретого кэша. В результате p95 не снижался после увеличения нагрузки, а граница насыщения проявлялась раньше. Для оценки релиза выбрали реалистичный сценарий с контролируемым состоянием кэша, а холодный кэш оставили отдельным тестом.
Да. Если большинство запросов обслуживается кэшем, средняя нагрузка и задержка базы данных могут выглядеть приемлемо даже при сильном ухудшении обработки промахов. Небольшая доля промахов способна определять p99, особенно если они требуют тяжёлых запросов или обращений к внешним системам.
Поэтому нужно анализировать задержки отдельно для попаданий и промахов, а не ограничиваться общей задержкой сервиса. Также важно контролировать долю промахов: при изменении ключей или истечении TTL она может резко вырасти.
Если пользователи обращаются к большему числу уникальных ключей, рабочий набор может превысить ёмкость кэша. Тогда записи начинают чаще вытесняться до повторного использования, и доля попаданий снижается.
К тому же увеличение нагрузки может ускорить истечение TTL относительно времени повторного обращения. Поэтому связь между нагрузкой и hit ratio не обязана быть монотонной: она зависит от размера рабочего набора, политики вытеснения, TTL и распределения популярности ключей.
Нет, прогрев нужен только для конкретного режима измерения. Он помогает отделить установившуюся работу с горячими данными от первоначальной стоимости заполнения кэша, но сам по себе не гарантирует реалистичность состояния.
Нужно определить, какой режим соответствует цели теста: доля горячих данных в обычной эксплуатации, поведение после рестарта, массовое истечение TTL или работа при смене набора ключей. Иначе можно получить стабильные метрики, относящиеся к искусственно благоприятному сценарию.