ПОЧЕМУ DEVOPS НУЖНА АНАЛИТИКА ПОТОКА ДАННЫХ

автор Анри Дюбуа-Феррьер

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

Хотя мы будем использовать Juttle, наш язык программирования потоков данных, чтобы проиллюстрировать наши положения, большинство из них в равной степени применимо к другим языкам и библиотекам потоков данных. Мы просто думаем, что Juttle - самый приятный и самый простой язык потоков данных (неудивительно!), Но мы поклонники многих других воплощений (таких как Riemann, Spark Streaming или Storm) и думаю, что они хороши в своих областях. Целевые области Juttle:

  • журнал аналитики
  • метрическая аналитика и
  • пользовательская аналитика.

Это те виды аналитики, которые имеют значение для DevOps и других операций, ориентированных на данные, например, для пользователей, нуждающихся в данных, которых иногда называют «маркетинговыми операциями» и «операциями роста». Общей чертой для всех этих видов аналитики является то, что взаимодействие между неструктурированными (или частично структурированными) данными, такими как журналы и предупреждения, со структурированными данными, такими как системные метрики и метрики приложений, делает анализ различных типов данных в одной структуре требованием для здравомыслие всех участников. Вот что может обеспечить поток данных.

Dataflow это, поток данных что?

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

«Программирование потока данных - это парадигма программирования, которая моделирует программу как ориентированный граф данных, передаваемых между операциями»

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

Простой пример

Давайте посмотрим на пример, вдохновленный DevOps, чтобы проиллюстрировать поток данных. В этом примере у нас есть поток поступающих веб-журналов в реальном времени, и мы хотим вычислить и визуализировать две ключевые статистические данные:

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

Программа Juttle для выполнения следующих действий (которую вы можете увидеть в действии на игровой площадке Juttle):

(
  events response_code = 500
    | reduce -every :1m: count() by hostname;
  source metadata
)
| join hostname
|(
  sort first_name
    | @barchart;
  reduce company_error_count = sum(error) by company
    | @timechart
)

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

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

Легкое сочетание партии и живого

С потоком данных аналитические вычисления выражаются одинаково, независимо от того, работают ли они с оперативными или историческими данными. Поведение во время выполнения не то же самое: в одном случае потоковый граф является долгоживущим, и в него постоянно вводятся входящие данные, а в другом - соответствующие исторические данные (из хранилища или из базы данных) вводятся, обрабатываются и расчет завершен. Но все это происходит под капотом во время выполнения, и точно так же, как вам не нужно беспокоиться о распределенных операциях при написании программы потока данных, вам не нужно беспокоиться о реальных и пакетных данных. За исключением, конечно, указания того, какие данные вас интересуют! Взгляните на этот пример на игровой площадке Juttle, чтобы увидеть блок-схему, которая обрабатывает как текущие, так и исторические данные.

Подходит для потоковой передачи данных, упорядоченных по времени

Большинство данных в DevOps носит временный характер. Потоки показателей, журналов или событий живут во временной области. И поток данных отлично подходит для потоков упорядоченных данных, потому что он абстрагирует временное упорядочение и делает его неявным. Поскольку точки проходят через потоковый граф по порядку, нет необходимости беспокоиться об индексах или сортировке точек. Например, предположим, что у нас есть поток журналов веб-запросов и мы хотим подсчитывать количество запросов каждые 5 секунд. Действительно простое вычисление, которое должно быть одинаково просто выражено. А в Джаттле это будет записано как:

... | reduce -every :5s: count() | ...

тогда как в SQL это можно было бы записать как:

select from_unixtime(floor(unix_timestamp(time)/5) * 5),
    count(*)
from table1
group by 1
order by 1;

(Это не означает, что вычисления, выраженные в SQL, по своей сути более сложны, чем на языке потоков данных, таком как Juttle. По большей части реляционный запрос для вневременных данных будет проще выразить в SQL, чем в Juttle. есть: разные домены, разные абстракции, разные языки!)

Вам может быть интересно, что делает поток данных для данных, которые не по своей природе, таких как списки активов или информация о клиентах, хранящаяся в базе данных SQL? Что ж, мы убедились, что Juttle может использовать и обрабатывать эти данные, включая отдельные записи (баллы на языке Juttle), которые не имеют временных меток. Например, в приведенном выше примере Juttle мы используем (потоковое соединение), чтобы аннотировать наш основной поток временных событий данными, поступающими из набора записей клиентов.

Декларативная

Декларативное программирование позволяет пользователю сосредоточиться на «что», а не на «как». Сопоставленный с областью потока данных, декларативный подход побуждает вас думать об обработке данных как о последовательности преобразований ваших данных. Вам не нужно беспокоиться обо всех механизмах управления потоком, отправки и извлечения данных, буферизации, перебора отдельных записей, распределенных операций и т. Д. - вам просто нужно объявить последовательность преобразований, необходимых для получения результата. (Конечно, эта последовательность преобразований сама по себе может быть сложной, если вы выполняете сложную обработку данных - и с декларативным языком потока данных вы можете сосредоточиться в первую очередь на вычислениях, а не на их механике).

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

Сборный

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

query | analyze | view

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

sub get_events(action) {
(
  events apptype="transactions" && action=action;
  source http://path/to/customer/data.json| join cust_id
}
export sub purchase_events() {
  get_events -action "purchase"
}
export sub refund_events() {
  get_events -action "refund"
}
export sub cart_add_events() {
  get_events -action "add_to_cart"
}

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

import 'sources.juttle' as sources;
sub analyze() {
 batch :1h: | reduce count() by user_id | sort count | head 5
}
sources.purchase_events | analyze | @table

Легкий. И, конечно, мы могли бы заменить источник Purchase_events другим в приведенном выше примере или аналогичным образом изменить анализ или часть просмотра потокового графа. (Если это похоже на лего, вы не удивитесь, узнав, что штаб-квартира Lego находится в… Ютландии!)

Простая распределенная работа

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

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

На ум приходит старая добрая модель оболочки Unix: полностью параллельное решение, которое может использовать несколько ядер / процессоров со сложной (внутренней реализацией), все абстрагированное от пользователя оболочки, пишущего конвейерные команды. (Полное раскрытие информации, хотя Jut Data Engine будет кластеризован при запуске, он изначально не сможет запускать один потоковый граф распределенным образом, и каждая программа будет работать на одном узле кластера).

Заворачивать

Мы считаем, что парадигма потока данных естественным образом подходит для выполнения аналитики * ops, где есть возможность обрабатывать и управлять данными нескольких типов (журналы, события, метрики) унифицированным способом, как в исторических (пакетных), так и в реальных доменах. бесценно. Devops является ярким примером этих операций, но маркетинг и рост также все чаще задают комбинированные вопросы, связанные с данными в реальном времени, историческими данными, событиями и показателями, которые лучше всего можно выразить с помощью потока данных. Пожалуйста, посетите Juttle Playground, чтобы ощутить вкус потока данных со вкусом Juttle!