Метрики, графики, статистика
![топ 100 блогов](/media/images/default.jpg)
Сделано было сначала в режиме «нечего думать, программировать надо», сейчас, когда мы планируем хранить глубокую историю, пришлось подумать получше.
Итак, какая ситуация вырисовывается с бесконечными метриками и замерами.
TL;DR отдельно решается задача усреднения замеров отдельных HTTP запросов до красивого графика и отдельно решается задача хранения данных для построения графиков. statsd, rrdtool, whisper(graphite), opentsdb, pulsedb.
Временные ряды
Есть две разных задачи:
1) сохранить, достать и нарисовать монотонный временной ряд
2) сгенерировать монотонный временной ряд из немонотонного временного ряда
Временной ряд — это набор упорядоченных пар (time,value).
Монотонный — это когда расстояния между соседними time в ряду постоянные. Т.е. раз в секунду, раз в 5 секунд и т.п. Тут надо сделать небольшое допущение на разрывы между областями монотонности, например всю ночь не было данных.
Описанные выше задачи действительно разные и решаются разными средствами. Поясню, почему я так говорю.
Человеку для анализа нужен график. График на экране компьютера — это почти всегда монотонный временной ряд, потому что пиксели занимают фиксированный размер. Почти — это если время нелинейно зачем-то сжимали.
Данные не всегда берутся монотонно и это важно понимать. Замеры скорости сети или загрузки cpu обычно интегрально замеряются (пишу интегрально, потому что вообще говоря это тоже дискретные замеры, просто наносекундные) раз в секунду и порождают монотонный временной ряд, пригодный для построения графика.
Другая история с характеристиками единичных HTTP запросов. У каждого запроса есть суммарное время, сколько он сожрал дискового времени, трафика и т.п. Эти запросы приходят как получится и их надо усреднять. Хранить все данные всех HTTP запросов можно, но не всегда нужно и всё равно с них надо строить монотонные усреднения.
Итак, для того что бы нарисовать график, нам надо получить монотонный временной ряд. Для того, что бы получить монотонный временной ряд, надо либо активно раз в секунду снимать замеры с cpu, сети, термометров или нейтронометра на raspbery, который мы опустили в ядерный реактор, либо надо каким-то образом усреднять шквал неоднородных данных.
Усреднение немонотонного временного ряда
Для усреднения немонотонного временного ряда до монотонного можно пользоваться разными вариантами. Например, мы хотим выяснить максимальное время запроса за секунду или среднее, или медиану или 90 перцентиль.
statsd именно это и делает. В него кидают немонотонный ряд, он наружу выдает раз в секунду какую-то цифирку.
riemann представляет из себя существенно более развесистую софтину чем statsd.
Тут очевидные проблемы с которыми воюют инженеры много лет. Как получить из грязного графика хорошую цифру, учитывая всякие ошибки замеров, искрящие контакты и прочие фуктуации, но при этом не вылить с водой ребенка, не пропустив реально неприятный выброс.
При снятии замеров можно выбрать очень примитивный способ: накапливать два числа: сумму и количество. Раз в секунду выдавать наружу среднее. Есть сотни других приемов, как не хранить всю массу чисел, т.е. нужны итерационные алгоритмы для рассчета агрегата.
Важно отметить, что когда пишут про Gauges, Counters, Flows и прочее, речь идет как правило о том, как из немонотонного ряда сделать монотонный.
Работа с монотонными рядами
С монотонными рядами приходится решать следующие проблемы:
1) как их хранить и показывать с разным разрешением
2) как их склеивать вместе
Первая проблема — как не хранить секундные замеры за 10 лет, учитывая что они нафиг никому не нужны. За прошлый год хранить дневные замеры, за этот часовые, за этот месяц минутные замеры, за эти сутки секундные замеры.
Т.е. надо через какой-то период времени брать монотонный временной ряд и увеличивать расстояние между точками. Сразу возникает вопрос: чего делать со значениями? Чаще всего достаточно просто среднего арифметического, но тут мы всё равно возвращаемся к предыдущему пункту: иногда нужно и похитрее.
Следующий вопрос про глубину хранения. rrdtool предлагает фиксировать по размеру, а не по глубине. В принципе, это устраивает большинство людей. При переполнении зоны секундных замеров происходит выталкивание в зону минутных замеров и т.п.
Вторая проблема — как объединять данные от разных источников. Например, когда мы собираем скорость трафика с компьютеров в сети, то на суммарном графике хочется видеть сумму. Если мы собираем показания датчиков температуры, то хочется видеть среднее (или среднее с весами, когда термометры в разные места вставлены).
При этом надо не забывать про проблему дырок во временных рядах. Что будет если в какую-то секунду с одного из трех серверов не пришел замер? Если ничего не делать, а просто суммировать цифры с одинаковыми секундами, то будет провал. Такой провал легко пропустить взглядом мимо (в человеческий мозг встроен охренненного качества интегральный анализатор графиков). Но что будет, если по какой-то причине систематически будет недополучаться каждый третий пакет? В этом случае дырки склеются и мы увидим испорченый, гладкий график сети.
Некоторые системы линейно апроксимируют дырки в рядах, некоторые системы забивают болт.
Чем хранить временные ряды
Если вкратце, то единого ответа тут нет. Гора денег лежит и ждет желающих.
RRDtool
Самое древнее, часто используемое, совершенно не масштабируемое решение. Ему надо при создании базы указать имена метрик и размеры. После этого засовывать в него тик за тиком. Добавлять на ходу метрики нельзя.
Whisper из Graphite
Whisper — это тот же RRDtool, но только в 500 строк кода на питоне, которые можно пофиксить и не ослепнуть.
Ceres как замена whisper, потому что в том есть фатальный недостаток.
OpenTSDB
Самое интересное на сегодняшний день готовое решение. Оно умеет динамически менять количество метрик, склеивать их, заполнять дырки, усреднять и т.п.
Проблема одна: пока поставишь, можно ослепнуть, потому что hadoop, hbase, gwt, gnuplot и прочий zookeeper, не к ночи он будет упомянут. Т.е. на управление всем этим хозяйством нужен java-compatible админ со всеми вытекающими.
Очень важная штука у OpenTSDB — это то, как хранятся временные ряды. В систему отправляются кортежи из имени метрики, времени, значения и набора тегов. Теги — это секретное оружие tsdb. Надо понимать, что внутри имя метрики представляет из себя склеенное входное имя и теги, но вопрос в том, как это потом достается.
Можно записать такие временные ряды:
output 1389787022 435600 media=ort,host=streamer1 output 1389787022 332600 media=zvezda,host=streamer1 output 1389787022 864600 media=zvezda,host=streamer2
Потом можно выбрать так:
sum:output:media=zvezda
и получить суммарную скорость раздачи по каналу zvezda со всех хостов. Или например можно так:
avg:temperature:hospital=sklif
получить график средней температуры по больнице.
Ещё есть возможность получить усредненный график, попросив выдать данные с шагом в 10 минут, усреднив.
TempoDB
Штука похожа на hosted opentsdb, но не то. Вроде как они не умеют склеивать соседние временные ряды.
librato
умеет собирать и аггрегировать метрики. В коментах мнения расходятся.
influxdb
Go + LevelDB. Развивается
KairosDB
Клон OpenTSDB но на кассандре и гуглкоде.
Blueflood
Ещё одна хранилка поверх кассандры.
pulsedb
Наша собственная база pulsedb. Предназначение — носимый и встраиваемый аналог opentsdb с возможностью риалтайм подписки на события.
Как-то так. Чего я упустил?
|
</> |