Modelagem de dados com Kafka? Tópicos e Partições

168

Uma das primeiras coisas em que penso ao usar um novo serviço (como um armazenamento de dados não RDBMS ou uma fila de mensagens) é: "Como devo estruturar meus dados?".

Eu li e assisti alguns materiais introdutórios. Em particular, considere, por exemplo, o Kafka: um sistema de mensagens distribuídas para processamento de logs , que escreve:

  • "um Tópico é o contêiner ao qual as mensagens estão associadas"
  • "a menor unidade de paralelismo é a partição de um tópico. Isso implica que todas as mensagens ... pertencentes a uma partição específica de um tópico serão consumidas por um consumidor em um grupo de consumidores".

Sabendo disso, qual seria um bom exemplo que ilustra como usar tópicos e partições? Quando algo deve ser um tópico? Quando algo deve ser uma partição?

Como exemplo, digamos que meus dados (Clojure) se pareçam com:

{:user-id 101 :viewed "/page1.html" :at #inst "2013-04-12T23:20:50.22Z"}
{:user-id 102 :viewed "/page2.html" :at #inst "2013-04-12T23:20:55.50Z"}

O tópico deve ser baseado user-id? viewed? at? E a partição?

Como eu decido?

David J.
fonte
3
Estranho isso fala sobre tópicos e partições, mas não necessariamente sobre a evolução dos dados dentro deles. E se você quisesse anexar agentes ou cabeçalhos de usuários a esses eventos de "visualização do usuário"? Como você evolui e comunica isso de uma maneira para os consumidores a jusante?
OneCricketeer 11/11/18

Respostas:

136

Ao estruturar seus dados para o Kafka, isso realmente depende de como eles devem ser consumidos.

Na minha opinião, um tópico é um agrupamento de mensagens de um tipo semelhante que serão consumidas pelo mesmo tipo de consumidor. Assim, no exemplo acima, eu só teria um único tópico e se você decidir enviar outro tipo de dados através do Kafka, você pode adicionar um novo tópico para isso posteriormente.

Os tópicos são registrados no ZooKeeper, o que significa que você pode ter problemas se tentar adicionar muitos deles, por exemplo, o caso em que você tem um milhão de usuários e decidiu criar um tópico por usuário.

Partições, por outro lado, é uma maneira de paralelizar o consumo das mensagens e o número total de partições em um cluster intermediário precisa ser pelo menos o mesmo que o número de consumidores em um grupo de consumidores para entender o recurso de particionamento. Os consumidores de um grupo de consumidores dividirão o ônus de processar o tópico entre si de acordo com a partição, de modo que um consumidor se preocupe apenas com as mensagens na própria partição que "estiver atribuída".

O particionamento pode ser definido explicitamente usando uma chave de partição no lado do produtor ou, se não for fornecido, uma partição aleatória será selecionada para cada mensagem.

Lundahl
fonte
5
Portanto, em vez de usar os tópicos como a maneira de obter dados por ID do usuário, sobrecarregando o Zookeeper, é melhor particionar por ID do usuário e fazer com que os consumidores baseados em ID do usuário se inscrevam em cada partição, se?
Ravindranath Akila
4
@RavindranathAkila Kafka is designed to have of the order of few thousands of partitions roughly less than 10,000. And the main bottleneck is zookeeper. A better way to design such a system is to have fewer partitions and use keyed messages to distribute the data over a fixed set of partitions. Faz-me pensar que não é a ferramenta certa para o que você descreveu - mas mais, o tópico seria "Eventos de exibição de página"? E todas as visualizações de página estariam nesse "tópico". Partições parecem mais sobre paralelismo e réplicas e outras coisas?
The Dembinski
Obrigado :) Finalmente tenho uma resposta: P
Ravindranath Akila
62

Depois de saber como particionar seu fluxo de eventos, o nome do tópico será fácil, então vamos responder a essa pergunta primeiro.

O @Ludd está correto - a estrutura de partição escolhida dependerá em grande parte de como você deseja processar o fluxo de eventos. Idealmente, você deseja uma chave de partição, o que significa que o processamento do evento é local da partição .

Por exemplo:

  1. Se você se importa com o tempo médio no site dos usuários, particione :user-id. Dessa forma, todos os eventos relacionados à atividade do site de um único usuário estarão disponíveis na mesma partição. Isso significa que um mecanismo de processamento de fluxo como o Apache Samza pode calcular o tempo médio no local de um determinado usuário apenas observando os eventos em uma única partição. Isso evita a necessidade de executar qualquer tipo de processamento global de partições dispendioso
  2. Se você se preocupa com as páginas mais populares do seu site, deve particionar por :viewedpágina. Novamente, o Samza será capaz de manter uma contagem das visualizações de uma determinada página apenas observando os eventos em uma única partição

Geralmente, estamos tentando evitar ter que confiar no estado global (como manter contagens em um banco de dados remoto como DynamoDB ou Cassandra) e, em vez disso, poder trabalhar usando o estado local da partição. Isso ocorre porque o estado local é uma primitiva fundamental no processamento de fluxo .

Se você precisar dos dois casos de uso acima, um padrão comum com o Kafka é primeiro particionar, digamos :user-id, e depois particionar novamente , :viewedpronto para a próxima fase do processamento.

Em nomes de tópicos - um óbvio aqui seria eventsou user-events. Para ser mais específico, você poderia usar com events-by-user-ide / ou events-by-viewed.

Alex Dean
fonte
8
Vi referências nas quais você publica os eventos em dois tópicos: um por trabalhador / uso pretendido. Nesse caso, pode haver dois tópicos, com dois esquemas de particionamento diferentes.
François Beausoleil
7

Isso não está exatamente relacionado à questão, mas, se você já decidiu a segregação lógica de registros com base em tópicos e deseja otimizar a contagem de tópicos / partições no Kafka, esse blog pode ser útil.

Principais tópicos em poucas palavras:

  • Em geral, quanto mais partições houver em um cluster Kafka, maior será a taxa de transferência possível. Permita que o máximo possível em uma única partição para produção seja pe consumo seja c . Digamos que seu rendimento alvo seja t . Então você precisa ter pelo menos partições max ( t / p , t / c ).

  • Atualmente, em Kafka, cada broker abre um identificador de arquivo do índice e do arquivo de dados de cada segmento de log. Portanto, quanto mais partições, mais alto é necessário configurar o limite de manuseio de arquivo aberto no sistema operacional subjacente. Por exemplo, em nosso sistema de produção, vimos um erro dizendo uma vez too many files are open, enquanto tínhamos cerca de 3600 partições de tópicos.

  • Quando um broker é encerrado de maneira não limpa (por exemplo, kill -9), a indisponibilidade observada pode ser proporcional ao número de partições.

  • A latência de ponta a ponta em Kafka é definida pelo horário desde a publicação de uma mensagem pelo produtor até a leitura da mensagem pelo consumidor. Como regra geral, se você se preocupa com a latência, provavelmente é uma boa ideia limitar o número de partições por broker para 100 x b x r , em que b é o número de intermediários em um cluster Kafka er é o fator de replicação.

Bitswazsky
fonte
4

Acho que o nome do tópico é a conclusão de um tipo de mensagem, e o produtor publica a mensagem no tópico e a mensagem de assinatura do consumidor por meio do tópico de assinatura.

Um tópico pode ter muitas partições. partição é boa para paralelismo. partição também é a unidade de replicação; assim, em Kafka, líder e seguidor também é dito no nível da partição. Na verdade, uma partição é uma fila ordenada cuja ordem é a mensagem que chegou. E o tópico é composto por uma ou mais fila em uma palavra simples. Isso é útil para modelar nossa estrutura.

O Kafka é desenvolvido pelo LinkedIn para agregação e entrega de logs. essa cena é muito boa como exemplo.

Os eventos do usuário em seu site ou aplicativo podem ser registrados pelo seu servidor da Web e, em seguida, enviados ao broker Kafka por meio do produtor. No produtor, você pode especificar o método de partição, por exemplo: tipo de evento (evento diferente é salvo em partição diferente) ou hora do evento (particionar um dia em período diferente de acordo com a lógica do aplicativo) ou tipo de usuário ou apenas nenhuma lógica e equilibrar todos os logs em muitas partições.

Sobre o seu caso em questão, você pode criar um tópico chamado "page-view-event" e criar N partições por meio de chaves hash para distribuir os logs em todas as partições uniformemente. Ou você pode escolher uma lógica de partição para fazer a distribuição de logs pelo seu espírito.

GuangshengZuo
fonte