Как стать автором
Обновить

Комментарии 15

Так надо при построении графиков по персентилям агрегировать не по среднему значению, а по максимальному. Тогда и получится ожидаемая метрика «максимальное время открытия страницы для 99% пользователей».
Такая аггрегация будет отличаться от правильного значения p99.

Это легко представить — допустим у нас в один пиксел графика попадает два периода:
— за первый период системы обслужила 1.000.000.000 запросов каждый из которых выполнен ровно за 1мс, поэтому p99=1мс
— за второй период система обслужила всего 100 запросов каждый из которых выполнен ровно за 1000мс, поэтому p99=1000мс

По вашему алгоритму итоговый p99 за суммарный период будет 1000мс, в то время как настоящий p99 должен быть 1мс (99% от 1.000.000.100 запросов точно обслужены за 1мс)
Да, вы правы. Но на практике этот метод работает — на графике за большой временной интервал ищутся пики, потом эти пики детализируются до индивидуальных точек при необходимости (мы снимаем данные раз в минуту, окно для расчета персентилей имеет размер в 80 секунд)

По моему опыту, временные ряды нужны только для двух целей — анализ пиковой нагрузки (max агрегация по нужному персентилю) и анализ средней нагрузки (avg агрегация по среднему арифметическому)
Если распределение внутри временного интервала каждый раз у вас примерно одинаковое, то вы получите примерно нужное значение p99.

Но в статье уже все и так сказано по этому поводу — никак не убавить и не прибавить: является ли ваш метод математически верным — нет; можно ли с этим жить — можно; можно ли извлекать из этого пользу — также можно.
С первого взгляда кажется логичным хранить точные значения персентилей с некоторым фиксированным значением (например с посекундным, т. е. p99 в течение секунды), а при построении графиков использовать max (или min по обстоятельствам) для вычисления y-координаты точки, в которую входит несколько интервалов.
Мне видится только один недостаток: нужно заранее определиться, какие персентили храним и рисуем.
Хранение по временным интервалам — возможно, но только потому что у нас нет другого выбора. В противном случае нужно хранить вообще всю выборку событий, а это HDFS/Hadoop/Spark и задержка при получении значений. То есть полноценная аналитика, вместо оперативного мониторинга.

Применение max к перцентилям — это неверное решение, я уже выше привел простейший контр-пример.

Поэтому автор и предлагает сохранять диапазонные метрики вместо перцентилей.
Но задача мониторинга — привлечь внимание к проблемным ситуациям. Если p99 = 1000ms может быть проблемой, то лучше это честно нарисовать + дать возможность изменять масштаб времени. Тогда будет прекрасно видно, что за одним «проблемным пикселем» скрывалось несколько интервалов и более подробно проанализируем именно интервал с p99 = 1000ms.
«Честно нарисовать» — значит нарисовать 1ms для p99 в случае необходимости объединить два временных интервала, и никак иначе. Для отображения 1000ms есть график максимумов или график p99.999999.
Вот еще неплохая заметка с одиозным названием на эту же тему
Если нужно вычислять только p99, то для точного вычисления перцентиля можно хранить не все данные, а только 1% данных, используя кучу. Если надо 99.9% перцентиль, то хранить надо только 0.1% данных и т.д.
На самом деле отличная попытка, но — нет :)

До есть — да, но только если вам заранее известно число событий которые поступят во временном периоде. Тогда мы действительно можем выделить место под min-heap размером 1% + 1 элемент. После того как период закончится, мы просто берем корневой элемент — и вот он, наш 99% перцентиль.

Но, если количество событий заранее не известно, нам придется держать две кучи: левую (max-heap) и правую (min-heap), чтобы иметь иметь позможно для перетекания элементов из одной кучи в другую, если баланс 99% на 1% по количеству будет нарушаться.

Вообще это классическая задача на собеседовании — как рассчитывать потоковую медиану (или вообще любой перцентиль) для каждого нового семпла за O(log n)
Пытаюсь пройти собеседование сообразить, значит для вычисления потокового перцентиля надо ожидаемый 1% + запас. Если за указанный период запас исчерпан, то придется брать другую технику, дающую уже приближенный результат.
В случае когда ни число событий, ни распределение значений заранее не известно — для расчета потокового перцентиля (любого) вам придется использовать две кучи, суммарно хранящие 100% всех данных.

stackoverflow.com/a/10657732/827139

Поскольку результат нам на ходу не нужен, проще копить массив и сортировать его в конце. А вот тут уже можно сделать финтиль: вместо полной сортировки за O(n log n) можно выполнить частичный QuickSort за O(n).

en.wikipedia.org/wiki/Selection_algorithm
Это было бы справедливо для неизвестного потока событий неограниченной длины. А у нас данные, которые по большей части повторяются изо дня в день. Если p99 надо считать, положим, раз в сутки, то можно применить две техники: точную, требующую только 1% данных, но работающую только на 99% всех днях, и приблизительную для 1% дней.
Характеристики потока неограниченной длины, особенно неизвестного, боюсь ни вы ни я за конечное время посчитать не сможем :)

Я только могу пересказать содержание статьи еще раз: вы вправе считать как угодно, если это вам помогает; но статья определяет способ как это делать правильно, без побочных эффектов и без каких-либо предположений о том когда, сколько и какие данные вам придут в мониторинг.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории