Posts Apache Kafka® é uma fila?
Post
Cancel

Apache Kafka® é uma fila?

Você já deve ter lido, assistido ou ouvido que o Apache Kafka® é uma fila. Não?

Ou afirmações como estas:

  • “Coloca na fila do Kafka!”
  • “Le aqui da minha fila no Kafka”
  • “Kafka é fila sim!”
  • “Ah, mas dá para fazer fila com o Kafka”

Bem, aqui serão listados os motivos e detalhes com o único objetivo de oferecer a você o entendimento completo sobre como é incorreto afirmar isso.

Então vamos desmitificar definitivamente sobre porque Kafka não é fila.

O que é uma fila?

Definição de fila:

  • uma estrutura de dados onde objetos são adicionados no final e removidos do inicio.

Somente a definição acima já deveria remover qualquer idéia sobre Apache Kafka® ser uma fila.

Em um tópico Kafka os eventos não são removidos depois de consumidos, graças a durabilidade.

Durabilidade

No Apache Kafka® os eventos depois de produzidos no tópico são mantidos lá por no mínimo 7 dias, isso em sua configuração padrão. Depois disso serão eliminados, mesmo que jamais tenham sido consumidos.

Viu? Nenhum comportamento de fila aqui. A durabilidade já é um argumento bem forte para demover essa idéia.

Garantia de Ordem

Em uma fila simples todos os dados adicionados são globalmente ordenados, ou seja, existe a garantia de que a ordem em que foram persistidos será globalmente mantida.

Um tópico no Apache Kafka® é subdivido em partições e a garantia de ordem é somente neste nível. Então, nos tópicos com várias partições não existe ordenação global entre elas.

Os detalhes sobre esta garantia estão no quarto paragráfo da documentação oficial , deixando muito claro qual será o comportamento.

Como você deve pensar, tópicos com apenas uma partição tem comportamento similar ao de fila. Então haverá a ilusão de que adicionar mais partições irá escalá-la. Não se engane, é somente uma ilusão mesmo.

Producer, Lotes e Retentativas

Ao contrário de filas tradicionais, que entregam assim-que-possível, no Kafka os eventos produzidos são loteados para uso racional da banda de rede e compressão. Portanto ao serem produzidos eles ainda permaneceram na origem por algum tempo.

Este comportamento é definido por configurações no Producer Apache Kafka®:

  • batch.size: tamanho do lote de eventos
  • linger.ms: estende o tempo local para montar lotes de eventos

Outro fato são as retentativas em caso de erro na entrega do lote de eventos ao broker. Quando isso acontece, automaticamente haverão reenvios que naturalmente poderão modificar a ordem entre os vários lotes que estão aguardando reconhecimento de entrega.

Isto é determinado pelas seguintes configurações:

É claro que filas tradicionais também implementam reenvios em caso e erro, mas jamais haverá mudança da ordem produzida. E isso quer dizer que enquanto a mensagem A não for entregue, B ficará aguardando, penalizando drasticamente a taxa de transferência. Mas Kafka não é fila, por isso há o compromisso com a ordenação estrita.

Consumer, Partições e Lotes

Apache Kafka® implementa o consumo paralelo e isso escala muito bem. E o número máximo de consumidores em um grupo de consumo está limitado a quantidade de partições presentes no tópico em questão.

Talvez você se pergunte:

  • “Se apenas um consumidor processar todas as partições do tópico, haverá comportamento de fila?”
    • Não. Os eventos já foram particionados na produção e no consumo não existe possibilidade de ordenação global.

E mesmo após consumidos, os eventos permanecem no tópico. O que é muito diferente de uma fila, onde eles serão removidos imediatamente após o consumo.

Portanto, durante um cenário de erro, jamais produza o evento novamente no tópico de onde ele foi consumido. Ele será duplicado e não “enfileirado”.

E não, criar mais grupos de consumo não vão escalar o processamento. 🤓

Similar ao batch.size, o Consumer também possui configurações para definir lotes de eventos e assim promover uso racional da banda e processamento. São elas:

Aliado a isso, existe a confirmação de offset. Onde o Consumer envia ao Kafka a confirmação de que o maior offset em um determinado lote de eventos já foi processado. Esta confirmação é identificada por:

  • grupo de consumo
  • nome do tópico
  • número da partição

Assim, caso o Consumer falhe outro retoma seu trabalho e segue de onde parou, por exemplo.

Mas como estamos falando de computação distribuída, isso pode falhar e os eventos serão consumidos novamente. Por este motivo a idempotência sempre é discutida e deve ser considerada quando se trabalha com Apache Kafka®.

Conclusão

Estes foram os fatos sobre como é incorreto afirmar que Apache Kafka® é fila e também como é incorreto dizer:

  • “ah, mas tecnicamente é possível se eu criar o tópico só com uma partição”
  • “eu posso desligar o loteamento de eventos para produzir e consumir um evento por vez”

Kafka não é fila. Ele implementa uma característica das filas. Que é:

  • dado um evento, este será processado por extamente um Consumer (dentro do grupo de consumo).

E este é um resumo sobre os sete itens abordados:

  1. Durabilidade: os eventos são duráveis
  2. Garantia de Ordem: não existe ordenação global no tópico
  3. Partições: unidades para paralelizar o consumo e ordenação local
  4. Lotes: produzir e consumir eventos em lote
  5. Retentativas: são executadas de forma transparente
  6. Grupo de Consumo: é o que faz Kafka ser muito diferente
  7. Idempotência: sempre tenha isso em mente

Se Kafka fosse fila, ele seria uma outra ferramenta qualquer como várias que existem por ai. Logo ele não seria tão popular na problemática dos eventos e sistemas distribuídos.


Photo by Dimitri Houtteman on Unsplash

Este post é licenciado sob CC BY 4.0 pelo autor.