Самый простой способ понять это — посмотреть, как это делают другие библиотеки потоковой обработки или сокращения карт (и я чувствую, что ваши интервьюеры видели эти библиотеки). В основном это уменьшение карты в реальном времени (вы также можете посмотреть, как это работает).
Я опишу два метода обработки событий. На самом деле большинству компаний необходимо делать и то, и другое.
Новая школа потоковой обработки (в реальном времени)
Давайте предположим, что на данный момент им нужны не фактические события, а более вероятный случай агрегатов (я думаю, что это и было целью вашего вопроса)
Примером проекта потоковой обработки является pipelinedb (у них в нижней части домашней страницы написано, как это работает).
- События переходят в очередь/кольцевой буфер
- Рабочий процесс считывает эти события пакетами и объединяет их в неполные сегменты или окна.
- Наконец, есть объединитель или редуктор, который принимает микропакеты и фактически выполняет обновление. Примером может служить подсчет событий. Поскольку мы используем очередь из вышеперечисленных, события поступают упорядоченно, и в зависимости от очереди у нас может быть несколько потребителей, которые выполняют операцию прочесывания.
Поэтому, если вам нужен подсчет минут, вы должны делать свертки в минуту и сохранять только сумму событий за эту минуту. Это оказывается довольно небольшим пространством, поэтому вы можете хранить это в памяти.
Если вам нужны эти подсчеты за месяц, день или даже год, вы просто суммируете все сегменты подсчета минут.
Теперь, конечно, есть большая проблема с этой техникой. Вам нужно заранее знать, какие агрегаты и стержни вы хотели бы собрать.
Но вы получаете очень быстрый поиск результатов.
Хранилище данных старой школы (разделение) и Map Reduce (пакетная обработка)
Теперь давайте предположим, что им нужны фактические события за определенный период времени. Это дорого, потому что если вы храните все события в одном месте, поиск и извлечение затруднены. Но если вы используете тот факт, что время иерархично, вы можете хранить события в дереве кортежей.
Причины, по которым вам нужны фактические события, заключаются в том, что вы выполняете специальные запросы и готовы ждать выполнения запросов.
- Вам нужна какая-то очередь для потока событий.
- Рабочий процесс читает очередь и разделяет события по времени. Например, у вас будет раздел на определенный день. Это похоже на шардинг. Многие системы хранения поддерживают это (например, разделы postgres).
- Когда вам нужно определенное количество событий за период, вы объединяете разделы.
- Разделение по существу иерархическое (минуты ‹ часы ‹ дни и т. д.), что означает, что вы можете выполнять над ними древовидные операции.
Существуют определенные способы хранения таких событий, которые называются данными временных рядов, чтобы индекс секционирования был автоматическим и быстрым. Они называются TSDB, дополнительную информацию о которых можно найти в Google.
Примером продукта TSDB может быть influxdb.
Теперь, возвращаясь к тому факту, что время (или, по крайней мере, то, как его представляют люди) представляет собой организованное дерево, мы можем преформировать операции распараллеливания. Это потому, что дерево является DAG (ориентированным ациклическим графом). С помощью DAG вы можете выполнять некоторый анализ и в основном рекурсивно работать с ветвями (также известными как fork/join).
Примером универсального продукта параллельного хранения может быть citusdb.
Теперь, конечно, у этого метода есть огромный недостаток. Это дорого! Даже если вы сделаете это быстро, увеличив количество узлов, вам придется платить за эти узлы (распределенные осколки). Теоретически производительность должна масштабироваться линейно, но на практике этого не происходит (детали я сохраню).
person
Adam Gent
schedule
25.05.2017
heap
для лучших результатов. - person 6324   schedule 25.05.2017