Eu fui a uma entrevista de emprego de engenheiro de dados. O entrevistador me fez uma pergunta. Ele me deu uma situação e me pediu para projetar o fluxo de dados para esse sistema. Eu resolvi isso, mas ele não gostou da minha solução e eu falhei. Gostaria de saber se você tem idéias melhores sobre como resolver esse desafio.
A questão era:
Nosso sistema recebe quatro fluxos de dados. Os dados contêm as coordenadas de identificação do veículo, velocidade e localização geográfica. Todo veículo envia seus dados uma vez por minuto. Não há conexão entre um fluxo específico e uma estrada ou veículo específico ou qualquer outra coisa. Há uma função que aceita coordenações e retorna um nome de seção da estrada. Precisamos saber a velocidade média por seção da estrada por 5 minutos. Finalmente, queremos escrever os resultados para Kafka.
Então, minha solução foi:
Primeiro, grave todos os dados em um cluster Kafka, em um tópico, particionado pelos 5-6 primeiros dígitos da latitude concatenados aos 5-6 primeiros dígitos da longitude. Em seguida, leia os dados por Streaming estruturado, adicionando para cada linha o nome da seção da estrada pelas coordenadas (há um udf predefinido para isso) e, em seguida, coletando os dados pelo nome da seção da estrada.
Como particiono os dados no Kafka pelos 5-6 primeiros dígitos das coordenadas, depois de converter as coordenadas no nome da seção, não é necessário transferir muitos dados para a partição correta e, portanto, posso aproveitar a operação colesce () isso não desencadeia uma reprodução aleatória completa.
Em seguida, calcule a velocidade média por executor.
Todo o processo ocorrerá a cada 5 minutos e gravaremos os dados no modo Anexar no coletor Kafka final.
Então, novamente, o entrevistador não gostou da minha solução. Alguém poderia sugerir como melhorá-lo ou uma ideia completamente diferente e melhor?
Respostas:
Achei essa pergunta muito interessante e pensei em tentar.
Conforme eu avaliei mais, sua tentativa em si é boa, exceto o seguinte:
Se você já possui um método para obter o ID / nome da seção de estrada com base na latitude e longitude, por que não chamar esse método primeiro e usar o ID / nome da seção de estrada para particionar os dados em primeiro lugar?
E depois disso, tudo fica bem fácil, então a topologia será
(Uma explicação mais detalhada pode ser encontrada nos comentários no código abaixo. Por favor, pergunte se algo não está claro)
Adicionei o código no final desta resposta. Observe que, em vez da média, usei soma, pois é mais fácil de demonstrar. É possível fazer a média armazenando alguns dados extras.
Eu detalhei a resposta nos comentários. A seguir, é apresentado um diagrama de topologia gerado a partir do código (graças a https://zz85.github.io/kafka-streams-viz/ )
Topologia:
fonte
O problema, como tal, parece simples e as soluções oferecidas já fazem muito sentido. Gostaria de saber se o entrevistador estava preocupado com o design e desempenho da solução em que você se concentrou ou com a precisão do resultado. Como outros se concentraram no código, no design e no desempenho, pesarei na precisão.
Solução de Streaming
À medida que os dados estão fluindo, podemos fornecer uma estimativa aproximada da velocidade média de uma estrada. Essa estimativa será útil na detecção de congestionamento, mas será desativada na determinação do limite de velocidade.
Solução em lote
Essa estimativa será desativada porque o tamanho da amostra é pequeno. Precisamos de um processamento em lote com dados completos de mês / trimestre / ano para determinar com mais precisão o limite de velocidade.
Leia os dados de um ano no data lake (ou Tópico Kafka)
Aplique UDF nas coordenadas para obter o nome da rua e o nome da cidade.
Calcule a velocidade média com uma sintaxe como -
Com base nesse limite de velocidade mais preciso, podemos prever tráfego lento no aplicativo de streaming.
fonte
Vejo alguns problemas com sua estratégia de particionamento:
Quando você diz que irá particionar seus dados com base nos primeiros 5 a 6 dígitos de lat de comprimento, não poderá determinar o número de partições kafka antecipadamente. Você terá dados assimétricos; em alguns trechos da estrada, você observará um volume alto do que outros.
E sua combinação de teclas não garante os mesmos dados da seção de estrada na mesma partição e, portanto, você não pode ter certeza de que não haverá embaralhamento.
As informações fornecidas pela IMO não são suficientes para projetar todo o pipeline de dados. Porque ao projetar o pipeline, como você particiona seus dados desempenha um papel importante. Você deve saber mais sobre os dados que está recebendo como número de veículos, tamanho dos fluxos de dados de entrada, o número de fluxos é fixo ou pode aumentar no futuro? Os fluxos de dados de entrada que você está recebendo são fluxos kafka? Quantos dados você recebe em 5 minutos?
mapValues
e emreduceByKey
vez de groupBy. Consulte isso .fonte
mapValues
e, dereduceBy
fato, pertence ao RDD de baixo nível, mas ainda terá um desempenho melhor nessa situação, pois primeiro acumula agregados por partição e, em seguida, embaralha.Os principais problemas que vejo com esta solução são:
Eu diria que a solução precisa fazer: leia do fluxo Kafka -> UDF -> seção da estrada de grupo -> média -> escreva no fluxo Kafka.
fonte
Meu design dependeria de
Se eu quiser escalar para qualquer número de contagens, o design ficaria assim
Questões cruzadas sobre esse design -
Algumas melhorias práticas possíveis neste design -
fonte