Introdução ao Apache Kafka

Cristiano Altmann
7 min readMay 1, 2018

--

Neste post pretendo dar uma breve introdução sobre um middleware amplamente utilizado pelo mercado e no qual venho me aprofundando nos últimos meses. Será o primeiro de uma série de posts que irei fazer compartilhando as informações que coletei de experiências, vídeos, livros e sites sobre esta ferramenta.

1. Apache Kafka

Apache Kafka é uma plataforma de streaming distribuído desenvolvida originalmente pelo Linkedin e posteriormente doada para a Apache Foundation.

Kafka é diferente dos sistemas tradicionais de mensageria. Conceitualmente, ele é um sistema de log distribuído. Isso significa que as mensagens enviadas ao Kafka são replicadas entre os nodos do Cluster e salvas de modo sequencial, o que garante que ao lermos os registros eles serão entregues na mesma ordem na qual foram enviados.

Kafka já é utilizado por mais de 1/3 das empresas da lista da fortune 500 e 7 dos 10 maiores banco do mundo.

Ele pode ser utilizado para diferentes finalidades. Você pode ver uma lista completa delas no site.

Kafka é uma excelente ferramenta para criarmos aplicações que trocam mensagens entre si, event sourcing, replicação de dados, etc. Mais detalhes aqui.

Boa parte disso se deve pelo fato das mensagens ficarem salvas em disco o que garante a consistência das mesmas, mesmo que um broker sofra uma falha.

Além disso, como as mensagens são replicadas entre os diferentes brokers, existe uma garantia em termos de disponibilidade, já que caso um broker falhe, outro broker assume o papel de leader e as mensagens podem continuar sendo escritas e lidas normalmente. Pretendo explicar com mais detalhes este processo em um post no futuro.

Fonte: https://kafka.apache.org

Como podemos ver acima, o kafka possui um componente central que é o cluster, responsável por receber e armazenar as mensagens e responder as requisições de consumers. As bibliotecas de Connectors e Stream, utilizam o conceito de Consumers e Producers para realizarem tarefas mais avançadas.

2. Publisher / Subscriber

Um bom uso para mensageria em geral é desacoplar as partes de um sistema que necessitam trocar informação. Uma chamada síncrona entre estas partes demanda que estes sistemas estejam conectados (acoplados) o que significa que eles precisam se conhecer para realizarem as operações. Uma alternativa para este paradigma é uso de troca de mensagens que adiciona um componente central responsável por receber / entregar estas mensagens.

Os dois patterns de mensageria mais conhecidos são Queue / Topic:

Queue: As mensagens são inseridas em ordem sequencial e lidas em ordem sequencial por 2 participantes: o que escreve a mensagem e o que lê a mensagem. Uma analogia seria uma mensagem individual no WhatsApp. Você envia as mensagens e o receptor as recebe na ordem que foram enviadas.

Topic: Semelhante a uma Queue porém ao invés de um receptor no tópico temos o conceito de broadcast. Um produtor envia mensagens para um tópico e as partes interessadas na informação assinam este tópico e passam a receber as mensagens enviadas.

Como veremos a seguir, Kafka possui um modelo híbrido, pois ele utiliza o conceito de tópico e partição, onde a partição pode ser considerada uma fila dentro de um tópico.

3. Log

Um log pode ser descrito como uma sequência temporal de mensagens, onde as novas mensagens sempre são adicionadas no final do log. Desta forma, uma mensagem enviada em t0 sempre estará posicionada antes de uma mensagem enviada em t1.

Cada mensagem dentro do log possui algumas informações:
1. Timestamp: data-hora da inserção
2. Offset: índice da mensagem na partição
3. Key: chave da mensagem
4. Value: a mensagem propriamente dita chamado de payload

Todas as mensagens dentro de uma partição serão um conjunto chave / valor.

4. Partição

Kafka utiliza o conceito de tópico onde as mensagens são agrupadas por uma classificação lógica. Por exemplo, se um tópico chamado employee_salaries existir, esperamos que dentro dele estejam armazenas mensagens desta categoria. Internamente, um tópico é dividido em partições. Observe a imagem abaixo:

Fonte: https://kafka.apache.org

Como podemos observar na imagem acima, este tópico possui 3 partições, cada uma com um número específico de mensagens e totalmente independentes.

Cada partição é um log isolado. Com isso podemos concluir que a ordem das mensagens só pode ser garantida dentro de uma partição. Se você deseja um tópico com 100% de garantia de ordem, então ele poderá ter apenas 1 partição. Porém, na maioria dos casos temos uma separação lógica dentro da garantia de ordem. Por exemplo, no nosso exemplo de employee_salaries deveríamos garantir a ordem do salário por cpf ou código do funcionário, de modo que a leitura garantiria a ordem por .

O importante de termos diversas partições é que estas partições são distribuídas em diferentes nodos, tendo diferentes leaders o que balanceia a carga de escrita e leitura entre diferentes brokers no cluster.

Como veremos a seguir, para cada grupo de consumidores, um único consumidor é responsável por cada partição. Desta forma, se quisermos paralelizar a leitura de um tópico, o número de partições irá definir o limite de paralelismo. Veremos mais adiante e em outros tópicos detalhes sobre isto.

5. Broker

Um broker é o componente responsável por receber as requisições de producers e consumers, armazenar as mensagens e executar a replicação das mesmas.

Os brokers são gerenciados por outro componente o zookeeper. Este componente é bastante utilizado para controlar os diferentes integrantes de um cluster.

Além das tarefas descritas acima, os brokers também realizam outras tarefas, como gerenciar os líderes de cada partição, realizar a limpeza de dados ou a compactação das mensagens.

Pretendo escrever em detalhes cada um destes tópicos avançados.

6. Producer

Producer é o componente responsável por escrever mensagens para um tópico. Um tópico pode ter um ou mais producers. Basicamente este componente deve se conectar ao cluster e escrever as mensagens para o tópico. É importante ressaltar que um dos grandes benefícios do Kafka em relação a outros sistema de mensageria é o throughput de escrita que ele suporta. Existem diversos benchmarks que demonstram conforme os links nas referências.

Estes números dependem muito do modelo de consistência de um producer. Esta consistência depende do modelo de garantia de escrita ou ack (acknowledgement) que define quantos brokers devem receber a mensagem para que a mensagem seja considerada como enviada. Quanto mais brokers receberem a mensagem, maior a garantia que temos que a mensagem foi persistida. Porém, a latência aumenta uma vez que mais componentes precisam dar o ack pra mensagem.

7. Consumer

Consumer é o componente responsável por realizar a leitura de um tópico. Estes componentes se registram em um tópico e realizam a leitura dos registros nas partições associadas a ele.

A primeira coisa importante de se falar sobre os consumers é que eles são responsáveis por armazenar o offset de leitura de cada partição. Isso é muito importante pois no design do Kafka, o cluster não é o responsável por armazenar o estado dos consumidores e sim o próprio consumer. Isso faz com que os brokers apenas respondam aos consumidores, entregando as mensagens a partir de um dado offset tornando o protocolo de conversação bastante simples.

Conforme dito anteriormente cada consumidor possui um único consumer group. Desta forma, cada vez que um consumidor é criado, ele é relacionado a um consumer group. Um consumer group pode conter diversos consumidores agrupados.

O importante disto é que cada mensagem existente em um tópico é entregue para apenas um consumer group. Veja a imagem abaixo:

Fonte: https://kafka.apache.org

Na imagem acima, possuímos um tópico com 4 partições. Estas partições estão distribuídas em dois clusters.

O consumer group A possui dois consumers (C1 e C2). Note que cada um deles esta recebendo mensagens de 2 partições. Mas cada partição do tópico esta associada a apenas 1 consumidor do Consumer Group A.

Da mesma forma, o Consumer Group B possui 4 consumidores, cada um recebendo mensagens de 1 partição.

O modelo de consumer group é utilizado para podermos adicionar mais instâncias de consumidores e garantir a entrega de apenas 1 mensagem a este grupo. Desta forma, podemos criar mais consumidores para processar as mensagens sem perder a garantia de entrega de uma única mensagem por tópico / consumer group.

8. Conclusão

Neste post tratei de alguns conceitos básicos e introdutórios sobre o Apache Kafka.

Apesar da arquitetura simples, o Kafka é uma ferramenta poderosa e possui ainda uma extensa biblioteca de clients, connectors e uma funcionalidade de stream nativa mas que também pode ser alinhada com ferramentas de mercado como Spark, Samza e Flink.

Irei tratar mais detalhes nos próximos posts.

Abaixo seguem alguns links que utilizei neste post:

  1. Kafka documentation
  2. https://www.confluent.io/press-release/confluent-grows-subscriptions-700-percent-2016-businesses-seize-power-real-time-data/
  3. Kafka, the definitive guide.
  4. https://engineering.linkedin.com/kafka/benchmarking-apache-kafka-2-million-writes-second-three-cheap-machines
  5. https://hackernoon.com/benchmarking-kafka-performance-part-1-write-throughput-7c7a76ab7db1

--

--

Cristiano Altmann

Gosto de estudar e compartilhar algumas coisas sobre a área de desenvolvimento de software na qual atuo a mais de 10 anos e sou apaixonado.