Я пошел на собеседование по работе с инженером данных Интервьюер задал мне вопрос. Он дал мне некоторую ситуацию и попросил спроектировать поток данных для этой системы. Я решил это, но ему не понравилось мое решение, и я потерпел неудачу. Я хотел бы знать, если у вас есть лучшие идеи, как решить эту проблему.
Вопрос был:
Наша система получает четыре потока данных. Данные содержат идентификатор автомобиля, скорость и координаты геолокации. Каждый автомобиль отправляет свои данные раз в минуту. Нет никакой связи между конкретным потоком, конкретной дорогой, транспортным средством или чем-то еще. Есть функция, которая принимает координаты и возвращает название участка дороги. Нам нужно знать среднюю скорость на участок дороги за 5 минут. Наконец, мы хотим записать результаты в Кафку.
Итак, мое решение было:
Сначала запишите все данные в кластер Кафки, в одну тему, разделенную на 5-6 первых цифр широты, соединенных с 5-6 первыми цифрами долготы. Затем считывание данных с помощью структурированной потоковой передачи, добавление для каждой строки имени участка дороги по координатам (для этого есть предварительно определенный udf), а затем сбор данных по имени участка дороги.
Поскольку я делю данные в Kafka по 5-6 первым цифрам координат, после перевода координат в имя раздела нет необходимости передавать большой объем данных в правильный раздел, и поэтому я могу воспользоваться операцией colesce () это не вызывает полное перемешивание.
Затем рассчитывается средняя скорость на одного исполнителя.
Весь процесс будет происходить каждые 5 минут, и мы будем записывать данные в режиме добавления в конечный приемник Kafka.
Опять же, интервьюеру не понравилось мое решение. Кто-нибудь может подсказать, как его улучшить или совершенно другую и лучшую идею?
Ответы:
Я нашел этот вопрос очень интересным и подумал о том, чтобы попытаться его решить.
Как я оценил далее, ваша попытка сама по себе хороша, за исключением следующего:
Если у вас уже есть метод для получения идентификатора / имени участка дороги на основе широты и долготы, почему бы сначала не вызвать этот метод и использовать идентификатор / имя участка дороги для разделения данных?
И после этого все довольно просто, поэтому топология будет
(Более подробное объяснение можно найти в комментариях в коде ниже. Пожалуйста, спросите, если что-то неясно)
Я добавил код в конце этого ответа, обратите внимание, что вместо среднего я использовал сумму, поскольку это проще продемонстрировать. Можно сделать среднее, сохраняя некоторые дополнительные данные.
Я подробно изложил ответ в комментариях. Ниже приведена схема топологии, сгенерированная из кода (спасибо https://zz85.github.io/kafka-streams-viz/ )
Топология:
источник
Проблема как таковая кажется простой, и предлагаемые решения уже имеют большой смысл. Мне интересно, беспокоился ли интервьюер о дизайне и производительности решения, на котором вы сосредоточились, или о точности результата. Поскольку другие сосредоточились на коде, дизайне и производительности, я буду весить на точность.
Потоковое решение
По мере поступления данных мы можем дать приблизительную оценку средней скорости дороги. Эта оценка будет полезна при обнаружении заторов, но будет отключена при определении ограничения скорости.
Пакетное решение
Эта оценка будет отклонена, потому что размер выборки невелик. Нам потребуется пакетная обработка данных за весь месяц / квартал / год, чтобы более точно определить ограничение скорости.
Прочитайте данные за годы из озера данных (или Кафка Тема)
Примените UDF к координатам, чтобы получить название улицы и название города.
Рассчитать среднюю скорость с синтаксисом вроде -
На основе этого более точного ограничения скорости мы можем прогнозировать медленный трафик в потоковом приложении.
источник
Я вижу несколько проблем с вашей стратегией разделения:
Когда вы говорите, что собираетесь разделить свои данные на основе первых 5-6 цифр лат длиной, вы не сможете заранее определить количество разделов kafka. У вас будут искаженные данные, так как на некоторых участках дороги вы будете наблюдать больший объем, чем на других.
И ваша комбинация клавиш в любом случае не гарантирует одинаковые данные участка дороги в одном и том же разделе, и, следовательно, вы не можете быть уверены, что не будет перетасовок.
Предоставленной ИМО информации недостаточно для проектирования всего конвейера данных. Потому что при разработке конвейера важную роль играет способ разделения данных. Вам следует узнать больше о данных, которые вы получаете, например, количество транспортных средств, размер входных потоков данных, фиксированное количество потоков или оно может увеличиться в будущем? Являются ли потоки входных данных, которые вы получаете, являются потоками Кафки? Сколько данных вы получите за 5 минут?
mapValues
иreduceByKey
вместо GroupBy. Отослать это .источник
mapValues
иreduceBy
действительно относится к низкоуровневому СДР, но все равно будет работать лучше в этой ситуации, так как сначала будет рассчитывать агрегат на раздел, а затем выполнять перемешивание.Основные проблемы, которые я вижу с этим решением:
Я бы сказал, что решение нужно сделать: читать из потока Кафки -> UDF -> секция группового пути -> средний -> записывать в поток Кафки.
источник
Мой дизайн будет зависеть от
Если я хочу масштабировать для любого количества отсчетов, дизайн будет выглядеть так
Перекрестные заботы об этом дизайне -
Возможны некоторые практические улучшения этого дизайна -
источник