Apache Kafka é conhecido por sua capacidade de processar uma enorme quantidade de eventos em tempo real. No entanto, para lidar com milhões de eventos, precisamos seguir certas melhores práticas ao implementar tanto os serviços de produção quanto os serviços de consumo do Kafka.
Antes de começara usar o Kafka em seus projetos, vamos entender quando usar o Kafka:
- Fluxos de eventos de alto volume. Quando sua aplicação/serviço gera um fluxo contínuo de eventos, como eventos de atividade do usuário, eventos de cliques em sites, eventos de dados de sensores, eventos de registro ou atualizações do mercado de ações, a capacidade do Kafka de lidar com grandes volumes com baixa latência é muito útil.
- Análise em tempo real. O Kafka é especialmente muito útil na construção de pipelines de processamento de dados em tempo real, onde os dados precisam ser processados assim que chegam. Ele permite que você transmita dados para mecanismos de análise como Kafka streams, Apache Spark ou Flink para análises/insights imediatos e processamento em fluxo ou em lote.
- Desacoplamento de aplicações. Ao atuar como um hub central de mensagens, ele pode desacoplar diferentes partes de uma aplicação, permitindo o desenvolvimento e a escalabilidade independentes de serviços e incentivando o princípio de segregação responsável.
- Integração de dados entre sistemas. Ao integrar sistemas distribuídos, o Kafka pode transferir dados de forma eficiente entre diferentes aplicações em equipes/projetos, atuando como um corretor de dados confiável.
Principais diferenças em relação a outros sistemas de fila
Abaixo estão as diferenças do Apache Kafka em relação a sistemas como ActiveMQ, ZeroMQ e VerneMQ:
Armazenamento Persistente
O Kafka armazena eventos em um log distribuído, permitindo a capacidade de reproduzir dados a qualquer momento e persistência de dados mesmo em caso de falhas de sistema/nó, ao contrário de algumas filas de mensagens tradicionais, que podem depender de armazenamento em memória como o Redis.
Particionamento
Os dados são particionados entre corretores/tópicos, permitindo o processamento paralelo de grandes fluxos de dados e alta taxa de transferência. Isso ajuda as threads consumidoras a se conectar ao particionamento individual, promovendo escalabilidade horizontal.
Grupos de Consumidores
Múltiplos consumidores podem se inscrever no mesmo tópico e ler de diferentes deslocamentos dentro de uma partição, permitindo padrões de consumo duplicados para diferentes equipes consumirem e processarem os mesmos dados para diferentes propósitos. Alguns exemplos são:
- Atividade do usuário consumida por equipes de ML para detectar atividades suspeitas
- Equipe de recomendação para construir recomendações
- Equipe de anúncios para gerar anúncios relevantes
Melhores Práticas para Produtores Kafka
Tamanho do Lote e Tempo de Espera
Configurando batch.size
e linger.ms
, você pode aumentar o throughput do seu produtor Kafka. batch.size
é o tamanho máximo do lote em bytes. O Kafka tentará agrupar antes de enviá-lo aos produtores.
Linger.ms
determina o tempo máximo em milissegundos que o produtor aguardará por mensagens adicionais para serem adicionadas ao lote para processamento.
A configuração dos parâmetros tamanho do lote
e linger.ms
ajuda significativamente no desempenho do sistema, controlando a quantidade de dados acumulados antes de enviá-los para os sistemas de processamento, permitindo um melhor throughput e reduzindo latências ao lidar com grandes volumes de dados. Isso também pode introduzir pequenos atrasos dependendo dos valores escolhidos. Especialmente, um grande tamanho de lote com um linger.ms
correto pode otimizar a eficiência da transferência de dados.
Compressão
Outra maneira de aumentar o throughput é habilitar a compressão por meio da configuração compression.type
. O produtor pode comprimir dados com gzip
, snappy
ou lz4
antes de enviá-los para os brokers. Para grandes volumes de dados, essa configuração ajuda na sobrecarga de compressão com eficiência de rede. Também economiza largura de banda e aumenta o throughput do sistema. Além disso, ao definir o serializador apropriado e o serializador de chave, podemos garantir que os dados sejam serializados em um formato compatível com seus consumidores.
Retentativas e Idempotência
Para garantir a confiabilidade do produtor do Kafka, você deve habilitar as retentativas e a idempotência. Ao configurar retries
, o produtor pode reenviar automaticamente qualquer lote de dados que não tenha recebido ack
pelo broker dentro de um número especificado de tentativas.
Acknowledgments
Esta configuração controla o nível de reconhecimento requerido pelo broker antes de considerar uma mensagem enviada com sucesso. Escolhendo o nível correto de acks
, você pode controlar a confiabilidade de sua aplicação. Abaixo estão os valores aceitos para esta configuração.
- 0 – o mais rápido, mas sem garantia de entrega da mensagem.
- 1 – a mensagem é reconhecida assim que é gravada no broker líder, proporcionando confiabilidade básica.
- all – a mensagem é considerada entregue apenas quando todas as réplicas a reconheceram, garantindo alta durabilidade.
Ajuste de Configuração com Base na Carga de Trabalho
você deve começar a rastrear métricas como taxa de envio de mensagens, tamanho do lote e taxas de erro para identificar gargalos de desempenho. Verifique e ajuste regularmente as configurações do produtor com base nas modificações ou atualizações de recursos/dados.
Melhores Práticas de Consumidores Kafka
Grupos de Consumidores
Cada consumidor Kafka deve pertencer a um grupo de consumidores; um grupo de consumidores pode conter um ou mais consumidores. Ao criar mais consumidores no grupo, você pode escalar para ler de todas as partições, permitindo processar um enorme volume de dados. A configuração group.id
ajuda aidentificar o grupo de consumidores ao qual o consumidor pertence, permitindo o balanceamento de carga entre vários consumidores consumindo do mesmo tópico. A melhor prática é usar IDs de grupo significativos para identificar facilmente os grupos de consumidores dentro da sua aplicação.
Confirmação de Offset
Você pode controlar quando sua aplicação confirma os offsets, o que pode ajudar a evitar a perda de dados. Existem duas maneiras de confirmar offsets: automática e manual. Para aplicações de alto desempenho, você deve considerar a confirmação manual para melhor controle.
- auto.offset.reset – define o que fazer quando um consumidor começa a consumir um tópico sem offsets comprometidos (por exemplo, um novo tópico ou um consumidor se juntando a um grupo pela primeira vez). Opções incluem
earliest
(ler desde o início),latest
(ler desde o final) ounone
(lançar um erro). Escolha “earliest” para a maioria dos casos de uso para evitar a perda de dados quando um novo consumidor se junta a um grupo.Controla como um consumidor começa a consumir dados, garantindo um comportamento adequado quando um consumidor é reiniciado ou adicionado a um grupo. - enable.auto.commit – ajuda a configurar para cometer automaticamente offsets periodicamente. Geralmente, definimos o valor como
false
para a maioria dos cenários de produção onde não precisamos de alta confiabilidade e cometer offsets manualmente dentro da lógica de sua aplicação para garantir processamento exato uma vez.Fornece controle para gerenciar commits de offset, permitindo mais controle sobre o processamento de dados. - auto.commit.interval.ms – intervalo em milissegundos no qual os deslocamentos são automaticamente confirmados se
enable.auto.commit
estiver definido comotrue
. Modifique com base no tempo de processamento do seu aplicativo para evitar perda de dados devido a falhas inesperadas.
Tamanho da Busca e Máximo de Registros na Poll
Essa configuração ajuda a controlar o número de registros recuperados em cada solicitação, configure fetch.min.bytes
e max.poll.records
. Aumentar esse valor pode ajudar a melhorar a taxa de transferência de suas aplicações, reduzindo o uso da CPU e o número de chamadas feitas aos brokers.
- fetch.min.bytes – o mínimo número de bytes a serem buscados de um broker em uma única solicitação de poll. Defina um valor pequeno para evitar chamadas de rede desnecessárias, mas não tão pequeno para evitar polling excessivo. Isso ajuda a otimizar a eficiência da rede, evitando solicitações pequenas e frequentes.
- fetch.max.bytes – o número máximo de bytes a serem obtidos de um corretor em uma única solicitação de pesquisa. Ajuste com base na memória disponível para evitar a sobrecarga dos trabalhadores consumidores. Isso reduz a quantidade de dados recuperados em uma única pesquisa, evitando problemas de memória. número de bytes a serem obtidos de um corretor em uma única solicitação de pesquisa. Ajuste com base na memória disponível para evitar a sobrecarga dos trabalhadores consumidores. Isso reduz a quantidade de dados recuperados em uma única pesquisa, evitando problemas de memória. a quantidade de dados recuperados em uma única pesquisa, evitando problemas de memória.
- max.poll.interval.ms – o tempo máximo para aguardar o retorno de uma solicitação de pesquisa antes de expirar.Defina um tempo limite adequado para evitar o bloqueio/lag do consumidor se os dados não estiverem disponíveis. Isso ajuda a evitar que os consumidores fiquem presos esperando mensagens por muito tempo. (Às vezes, os pods do k8s podem reiniciar se as sondagens de vitalidade forem afetadas).
Atribuição de Partição
Esta é a estratégia usada para atribuir partições (partition.assignment.strategy
) aos consumidores dentro de um grupo (por exemplo, range
, roundrobin
). Use range
para a maioria dos cenários para distribuir uniformemente as partições entre os consumidores. Isso permite uma distribuição de carga equilibrada entre os consumidores de um grupo. a maioria dos cenários para distribuir uniformemente as partições entre os consumidores. Isso permite uma distribuição de carga equilibrada entre os consumidores de um grupo.
Aqui estão algumas considerações importantes antes de usar o Kafka:
- Complexidade. A implementação do Kafka requer uma compreensão mais profunda dos conceitos de sistemas distribuídos, como particionamento e gerenciamento de offset, devido aos seus recursos e configurações avançados.
- Monitoramento e gerenciamento. Implementar monitoramento e gerenciamento de clusters Kafka é importante para garantir alta disponibilidade e desempenho.
- Segurança. Implementar práticas de segurança robustas para proteger dados sensíveis que circulam pelos tópicos do Kafka também é importante.
A implementação dessas melhores práticas pode ajudá-lo a escalar suas aplicações baseadas em Kafka para lidar com milhões/bilhões de eventos. No entanto, é importante lembrar que a configuração ideal pode variar com base nos requisitos específicos de sua aplicação.
Source:
https://dzone.com/articles/best-practices-for-scaling-kafka-based-workloads