В настоящий момент мы проводим эксперименты по применению ClickHouse к нашей системе потоковой агрегации событий. В общем и целом, нам удалось найти схему хранения, которая удовлетворяет нашим задачам. Осталось дело за одним нюансом — мы ждём кастомного партицирования. Нужно оно нам из соображений партицирования — мы не хотим хранить месяц данных (на самом деле — два, т.к. удалять можно только по месяцу), т.к. нам нужно максимум 1-2 дня.
Когда система войдёт в production использование, мы выпустим статью на эту тему.
Ваши замечания вполне справедливы, однако я не был бы столь категоричен насчёт этого:
HDR выглядит явным фаворитом уже из описания
Вставка в него, безуловно, быстра. Однако, как я упоминал выше, у нас все вычисления происходят на M/R, что означает что модель у нас не мутабельна (т.е. мы не производим модификации) — бенефиты от CAS на элементы массива счётчиков нам бесполезны
Необходимость иметь представление о верхней границе диапазона измеряемых значений. Поначалу мы считали, что имплементация с такими ограничениями для нас неприемлема, но со временем решили включить её в API системы дополнительно, наряду с неограниченными рядами на основании Algebird.
В BI мы разрабатываем распределённые приложения для обработки данных. Стек технологий — Spark + Hadoop + Java, т.к. Java нативна для Хадупа. Система построена в тесной интеграции с PHP-backend'ом (существует DSL для описания событий, PHP-API для их отправки, различные GUI для работы с данными), так что можно смело называть связку «Java + PHP».
Внутри система представляла собой обыкновенный сайт, написанный функциональным стилем.
К проектам на PHP, как правило, применимо «процедурным» стилем (если имелось в виду нагромождение функций, а не оперирование функциями высших порядков).
Спасибо за ещё один инструмент в копилку!
Как я написал в комментарии ниже, за счёт spawn'а remote shell, мы рискуем оставить после себя долгоиграющий неприбитый процесс, что для нас неприемлемо. Ну и да, опять — где брать список хостов, и т.д.
В общем случае, любой кластер, где производятся подобного рода вычисления, является statless. Это означает, что после выполнения программы, все артефакты (временные файлы), которые она наплодила, должны быть уничтожены. Для сохранения каких-либо результатов следует использовать shared-ресурсы (база данных, HDFS).
Конкретно в случае нашей задачи, мы на Python производим вычисления и записываем результат в файл в текущей рабочей директории. Когда бизнес-логика отработала, файл заливается в HDFS (из этого же процесса).
В случае краха процесса/уничтожения YARN контейнера, рабочая директория контейнера уничтожается, и мы не мусорим локальную FS кластера.
Команды транспорта опускаем, рассмотим то, что запускается на удалённой стороне:
/bin/sh -c "/usr/bin/uptime"
При выполнении этой команды, мы получим на удалённой стороне последовательность fork-exec, которая сначала запустит /bin/sh, а затем — fork-exec для /usr/bin/uptime.
Я запустил paexec, указав в качестве команды пользователя /usr/bin/sleep 1000, затем прервал выполнение paexec через SIGINT.
Что мы получаем в результате? Правильно — на удалённом хосте у нас висит /usr/bin/sleep (аналог нашего долгоиграющего приложения).
Т.е. при прерывании работы управляющего приложения, дочерние не прибиваются. Именно по этой причине, мы в своей реализации не используем spawn shell'а, а сразу зовём execve приложения.
Честно говоря, мы не сильно углублялись в нутра parallel, т.к. широкого применения он у нас не имеет, а предварительные изыскания показали его неприменимость к нашей задаче.
Помимо загруженности хоста есть ещё понятие «доступности» (выключен, например, или gracefully выводится из эксплуатации :). Также, нам не хочется держать где-то в конфиге список хостов и их технические характеристики — пусть это будет головной болью кластер-менеджера.
Скажите, пожалуйста, какова частота обновления точек у одной метрики, с которой работает Anomaly Detector? Т.е. каков временной юнит, которым оперирует AD?
И ещё вопрос — какова «пропускная способность» детектора?
Т.е. сколько метрик обслуживает инстанс AD, в пересчёте на ядра/память?
Помимо Android, Java используется только в среде BI (Hadoop, Spark), т.е. массово распространения не имеет.
В связи с этим, тематические Java конференции посетило малое количество народа, и их не включили в список.
У Вас в драйвере по таймеру запускается updateConditions(), который модифицирует rdd.
1.) Насколько я понимаю, размер этой коллекции должен быть мал, т.к. она должна быть послана через broadcast на всех executor'ов — это так? Если нет — расскажите, пожалуйста.
2.) У меня в приложении есть такая же необходимость — со временем обновлять некий конфиг, и доставлять его на executor'ов. Но, согласно документации, чтобы применилось синхронно на всех executor'ах, это должен быть либо ручной broadcast, либо неявный — через сериализатор лямбд. Недокументировано то, что при обновлении в драйвере, изменения разъедутся по executor'ам. Насколько стабильно/синхронно у Вас применяются эти изменения? Или в Вашем случае допустимо несинхронное применение изменений, и Вы о нем знаете?
Наверное, здесь произошла «типичная подмена понятий». Вы имели в виду из executor'а (исполнителя юзерских лямбд)? А какого рода конфигурация нужна? Для своих нужд я вполне обхожусь broadcast'ами, или сериализуемым своим классом с настройками.
Согласен, выглядит несколько пугающе, но при рассмотрении вариантов:
1.) То же самое, в XML (плюсов с ходу не вижу, из минусов — потребить больше памяти, написать парсер конфига)
2.) Инструкции, подобно тому, как PHP: lxr.php.net/xref/PHP_5_5/Zend/zend_language_parser.y (опять же, подсистему парсинга, но теперь уже — псевдокода конфига)
3.) Сделать OOP-интерфейс для правил переходов $State
->when($ContextPredicate)
->then($Transition)
->done($ReverseTransition); // (а-ля Promises, не обещает быть меннее монстроузным)
и для правил форматирования
$ClassToken
->inContext($ClassDefinitionContext)->do($IndentIncreateAction)
->inContext($ClassReferenceContext)->do($IndentIncreateAction);
4.) Текущая реализация (минимальный memory footprint, возможность программирования конфига на языке приложения)
Последний вариант мне кажется наиболее оптимальным.
Наш pre-receive хук проверяет плохое форматирование, используя phpcf. Т.е. производится форматирование измененных строк, и, если там код не отформатирован, коммит не проходит.
Когда система войдёт в production использование, мы выпустим статью на эту тему.
К проектам на PHP, как правило, применимо «процедурным» стилем (если имелось в виду нагромождение функций, а не оперирование функциями высших порядков).
Как я написал в комментарии ниже, за счёт spawn'а remote shell, мы рискуем оставить после себя долгоиграющий неприбитый процесс, что для нас неприемлемо. Ну и да, опять — где брать список хостов, и т.д.
Конкретно в случае нашей задачи, мы на Python производим вычисления и записываем результат в файл в текущей рабочей директории. Когда бизнес-логика отработала, файл заливается в HDFS (из этого же процесса).
В случае краха процесса/уничтожения YARN контейнера, рабочая директория контейнера уничтожается, и мы не мусорим локальную FS кластера.
Из входных данных проекта https://github.com/cheusov/paexec/:
Очень похоже на то, что выполняет наша утилита.
А здесь: https://github.com/cheusov/paexec/blob/master/paexec/paexec.pod
И здесь мы схожи.
Выходит, что реализации схожи, и, с моей точки зрения, обе могут называться «распределённым xargs» :)
Со своей колокольни обратил внимание на пару вещей, из-за которых мы бы не стали этот инструмент брать в рассмотрение:
https://github.com/cheusov/paexec/blob/master/paexec/paexec.pod
Мы ограничены форматом output'а того, что мы запускаем на удалённой стороне.
Последовательность fork-exec
Команды транспорта опускаем, рассмотим то, что запускается на удалённой стороне:
При выполнении этой команды, мы получим на удалённой стороне последовательность fork-exec, которая сначала запустит /bin/sh, а затем — fork-exec для /usr/bin/uptime.
Я запустил paexec, указав в качестве команды пользователя /usr/bin/sleep 1000, затем прервал выполнение paexec через SIGINT.
Что мы получаем в результате? Правильно — на удалённом хосте у нас висит /usr/bin/sleep (аналог нашего долгоиграющего приложения).
Т.е. при прерывании работы управляющего приложения, дочерние не прибиваются. Именно по этой причине, мы в своей реализации не используем spawn shell'а, а сразу зовём execve приложения.
Помимо загруженности хоста есть ещё понятие «доступности» (выключен, например, или gracefully выводится из эксплуатации :). Также, нам не хочется держать где-то в конфиге список хостов и их технические характеристики — пусть это будет головной болью кластер-менеджера.
И ещё вопрос — какова «пропускная способность» детектора?
Т.е. сколько метрик обслуживает инстанс AD, в пересчёте на ядра/память?
В связи с этим, тематические Java конференции посетило малое количество народа, и их не включили в список.
round trip time из МСК/СПБ до вашего ДЦ можете привести, пожалуста?
1.) Насколько я понимаю, размер этой коллекции должен быть мал, т.к. она должна быть послана через broadcast на всех executor'ов — это так? Если нет — расскажите, пожалуйста.
2.) У меня в приложении есть такая же необходимость — со временем обновлять некий конфиг, и доставлять его на executor'ов. Но, согласно документации, чтобы применилось синхронно на всех executor'ах, это должен быть либо ручной broadcast, либо неявный — через сериализатор лямбд. Недокументировано то, что при обновлении в драйвере, изменения разъедутся по executor'ам. Насколько стабильно/синхронно у Вас применяются эти изменения? Или в Вашем случае допустимо несинхронное применение изменений, и Вы о нем знаете?
1.) То же самое, в XML (плюсов с ходу не вижу, из минусов — потребить больше памяти, написать парсер конфига)
2.) Инструкции, подобно тому, как PHP: lxr.php.net/xref/PHP_5_5/Zend/zend_language_parser.y (опять же, подсистему парсинга, но теперь уже — псевдокода конфига)
3.) Сделать OOP-интерфейс для правил переходов
$State ->when($ContextPredicate) ->then($Transition) ->done($ReverseTransition); // (а-ля Promises, не обещает быть меннее монстроузным)
и для правил форматирования
$ClassToken ->inContext($ClassDefinitionContext)->do($IndentIncreateAction) ->inContext($ClassReferenceContext)->do($IndentIncreateAction);
4.) Текущая реализация (минимальный memory footprint, возможность программирования конфига на языке приложения)
Последний вариант мне кажется наиболее оптимальным.
По инциденту заведен Issue на github, спасибо за репорт.