Spark Streaming с данными без схемы
В настоящее время у нас есть настройка конвейера данных, где мы читаем необработанные данные из одной темы Kafka с помощью Logstash и записываем их в ElasticSearch.
Данные в этом разделе представлены в формате JSON, но каждая строка может принадлежать совершенно другому бизнес-домену, поэтому она может иметь совершенно другую схему. Например:
запись 1: "{"id":1,"model":"model2","updated":"2017-01-1T00:00:00.000Z","domain":"A"}
запись 2: "{"id":"some_compound_key","result":"PASS","domain":"B"}
Вы можете видеть, что схема не только отличается, но и на самом деле конфликтует (id - это целое число в первой записи и строка во второй).
Есть только две гарантии - каждая запись является допустимой записью JSON, и у каждой есть поле "домен". Даже записи с одним и тем же значением домена могут иногда иметь разные схемы.
Теперь у нас есть требование обогащать и преобразовывать эти данные по мере их прохождения по конвейеру (вместо того, чтобы делать это позже с ETL), и мы рассматриваем несколько способов сделать это. Предостережение заключается в том, что поскольку данные не имеют унифицированной схемы, преобразование необходимо выполнять построчно:
1) Продолжить использовать Logstash - можно смоделировать конвейер преобразования, который нам нужен, для каждого домена, используя набор фильтров и условных выражений Logstash.
Кроме того, его легко поддерживать и развертывать, поскольку Logstash периодически перезагружает конфигурацию во время выполнения, поэтому для изменения / добавления логики преобразования нам нужно всего лишь удалить новый файл конфигурации в каталоге conf.
Недостатком, однако, является то, что очень трудно обогащать данные с помощью Logstash из внешних источников.
2) Использовать потоки Kafka - это кажется очевидным выбором, поскольку он хорошо интегрируется с Kafka, позволяет объединять данные из нескольких потоков (или внешних источников) и не имеет требований к схеме - легко преобразовывать данные построчно.
Недостатком здесь является то, что трудно изменить логику преобразования во время выполнения - нам нужно либо перекомпилировать и повторно развернуть приложение, либо обернуть его некоторым API, который будет генерировать и компилировать код Java во время выполнения, или каким-либо другим сложным решением.
3) Используйте Spark Streaming - мы уже используем Spark для пакетной обработки, поэтому было бы здорово, если бы мы могли использовать его для потоковой передачи, чтобы сохранить наш стек как можно более простым.
Однако я не уверен, что Spark может даже поддерживать потоковые данные, у которых нет единой схемы, и возможно ли выполнять преобразования для каждой строки.
Все примеры, которые я видел (а также наш собственный опыт пакетной обработки Spark) предполагают, что данные имеют четко определенную схему, что не является нашим вариантом использования.
Может ли кто-нибудь пролить свет на то, возможно ли то, что нам нужно, с помощью Spark Streaming (или структурированного потокового вещания), или мы должны придерживаться Logstash / Kafka Streams?
1 ответ
Отказ от ответственности: я активный участник Kafka Streams.
Я не знаком с Logstash, но из того, что вы описали, это кажется наименее привлекательным решением.
О Spark Streaming. Даже если я не большой поклонник этого, я думаю, что вы могли бы сделать обработку, которую вы хотите сделать с ним. Структурная потоковая передача не будет работать, насколько я понимаю, так как для нее требуется фиксированная схема, но Spark Streaming должна быть более гибкой. Однако использование Spark Streaming не сделает его более простым по сравнению с Kafka Streams (но, скорее всего, сложнее). У меня нет личного опыта запуска Spark Streaming на производстве, но я слышал много жалоб на нестабильность и т. Д.
О "недостатках" ручьев Кафки вы указали. (1) я не уверен, зачем вам нужна генерация кода и т. Д. И (2), почему это может отличаться в Spark Streaming? Вы должны написать свою логику преобразования в обоих случаях, и если вы хотите изменить ее, вам нужно повторно развернуть ее. Я также считаю, что обновление приложения Kafka Streams с помощью "скользящих отскоков" намного проще и позволяет сократить время простоя по сравнению со Spark Streaming, для которого вам необходимо остановить обработку между ними.
Было бы полезно понять, какую "модификацию кода во время выполнения" вы хотите сделать, чтобы дать более подробный ответ здесь.