Compreensão profunda da série Kafka (quatro) -Kafka replicação de armazenamento e processo de processamento de pedidos
Lista de artigos da série
Artigos da série de guias oficiais de Kakfa
Prefácio
Esta série é minha transcrição e pensamentos depois de ler o livro "The Definitive Guide to Kafka".
texto
Associação de cluster
Kafka usa o zookeeper para manter o relacionamento entre os membros do cluster. Cada corretor possui um identificador exclusivo (ou seja, clientId, que também pode ser gerado automaticamente).
- Ao iniciar um broker, o broker registra seu ID criando um nó temporário no zookeeper. O caminho é: / brokers / ids. Portanto, quando o broker ingressar ou sair do cluster, esses membros receberão notificações relevantes.
- Se você iniciou um corretor com ID A, também deve iniciar um corretor com ID A. Então, o corretor obterá um erro. ( Dois corretores com o mesmo ID não podem existir ao mesmo tempo )
- Se o broker mencionado anteriormente com ID A for completamente encerrado e, em seguida, um novo broker (ID também A) for iniciado, o novo broker se unirá imediatamente ao cluster e terá a mesma partição e tópico do antigo broker.
Controlador
O controlador é essencialmente um corretor, mas em comparação com outros corretores comuns, ele também tem a função de eleição do líder da partição.
Qual é o padrão produzido pelo controlador?
A primeira inicialização será bem-sucedida no dispositivo de controle do broker kafka , ele criará um nó / controlador temporário no zookeeper.
Quando os corretores posteriores forem iniciados, eles também tentarão criar nós / controladores temporários no zookeeper, mas receberão uma exceção "nó já existe" e, em seguida, perceberão que já existe um controlador no cluster, e então eles os objetos serão criados no nó do controlador para que possam ser notificados das alterações neste nó.
Se o controlador e o zookeeper estiverem desconectados, o que acontecerá a seguir?
1. Então, o nó temporário no zookeeper desaparecerá.
2. Em seguida, outros corretores no cluster serão notificados do desaparecimento do nó controlador por meio do objeto de observação. Eles tentarão se tornar o novo controlador.
3. Em seguida, siga os padrões acima, o primeiro corretor que criar com sucesso um nó temporário no zookeeper se tornará o novo controlador.Uma vez que o nó temporário é criado com sucesso, outros corretores que estão tentando se tornar um novo controlador receberão as exceções correspondentes.
Haverá dois controladores? Se sim, o que devo fazer?
O primeiro é sim.
Exemplo: Suponha que o controlador original seja considerado inativo devido ao congestionamento da rede e, uma vez que o nó temporário desapareça, outros corretores não começarão a competir para se tornar o controlador. Quando um novo controlador é criado, a rede do controlador antigo volta ao normal. Depois, há um problema típico: problema de
divisão do cérebro
Como Kafka resolve o problema do cérebro dividido?
1. Volte para as etapas anteriores. Se um controlador desligar e outros corretores elegerem um novo controlador, eles devem criar um novo objeto de observação no novo controlador.
2. Então, o novo controlador obterá uma época de controlador totalmente nova com um valor maior por meio da operação de incremento condicional do zookeeper , que pode ser entendido como a chave primária do banco de dados.
3. Então, se outros corretores subsequentemente receberem uma mensagem contendo a época antiga do controlador após saber a época do controlador mais recente atual, eles serão ignorados.
Replicação kafka
A função de replicação do Kafka pode ser considerada um núcleo da arquitetura Kafka.
Aqui está um breve resumo da estrutura organizacional de Kafka.
- Use tópicos para organizar os dados.
- Cada tópico é dividido em várias partições. (Partição pode ser entendida como compartilhar a quantidade de dados e armazená-los separadamente)
- Existem várias cópias de cada partição. (Cópia pode ser entendida como cópia de dados, usada para alta confiabilidade)
- A cópia é salva no corretor.
Tipo de cópia:
- Cópia do chefe
1. Conforme mencionado acima, cada partição pode ter várias cópias.
2. Mas apenas uma cópia é a cópia chefe.
3. Todas as solicitações do produtor e do consumidor passam pela cópia líder.
- Cópia do seguidor
1. Todas as cópias, exceto a cópia líder, são cópias seguidoras.
2. A cópia do seguidor não processa nenhuma solicitação.
3. Sua única função é copiar mensagens da cópia do líder para manter a consistência. E quando a cópia do boss for colapsada, eleja uma nova cópia do boss.
Aqui está uma explicação de por que a cópia do seguidor não processa nenhuma solicitação.
1. Suponha que um usuário faça a mesma solicitação de consumo duas vezes sucessivamente. Existem duas cópias seguidoras, uma A e uma B, e A sincronizou com a cópia mestre, mas B não.
2. Pela primeira vez lida da cópia do seguidor A, a mensagem lida é olá.
3. A segunda leitura da cópia B do seguidor, a mensagem lida é hello world.
4. Então o problema está chegando, os dados lidos pela segunda vez são dados sujos e os dados reais são A, o que causa inconsistência de dados. Portanto, o Kafka permite de maneira direta e simples que todas as solicitações do consumidor passem pela réplica master.
Então o problema surge novamente: se uma cópia mestre falhar e as outras cópias escravas forem eleitas, como garantir que os dados salvos na cópia escolhida sejam completos?
Antes de responder a esta pergunta, deixe-me falar sobre dois conceitos, cópias síncronas ou não sincronizadas.
- Cópia fora de sincronia
1. Em primeiro lugar, a seguinte premissa, a fim de manter a sincronização com a cópia do líder, os seguidores precisam enviar uma solicitação de dados para a cópia do líder. (Pode ser considerado um pedido do consumidor).
2. O líder envia a mensagem de resposta ao seguidor, e essas mensagens de solicitação contêm o deslocamento que o seguidor deseja receber a mensagem, e o deslocamento está em ordem.
3. Se o seguidor não solicitou nenhuma mensagem em 10s ou não solicitou os dados mais recentes em 10s, esta cópia é considerada fora de sincronia.
Nota: Este 10s pode ser especificado configurando o parâmetro replica.lag.time.max.ms
- Sincronizar cópia
As notícias obtidas pela solicitação contínua são sempre as mais recentes, tal cópia é chamada de cópia sincronizada.
Então, de volta à pergunta anterior: como garantir que os dados estejam completos?
Em Kafka, quando o líder falha, apenas a cópia sincronizada pode ser selecionada como o novo líder.
Processando pedido
- Cada broker executará um thread de aceitação em cada porta que monitora.Este thread criará uma conexão e a entregará ao thread de processador para processamento.
- O thread do Processor é responsável por obter mensagens de solicitação do cliente, colocando-as na fila de solicitação e, em seguida, obter mensagens de resposta da fila de resposta e enviá-las ao cliente.
O processo geral é o seguinte:
Existem dois tipos comuns de threads de IO na figura: (threads de IO são responsáveis pelo processamento de mensagens da fila)
- Solicitação de produção: a solicitação enviada pelo produtor, incluindo a mensagem que o cliente deseja escrever para o corretor.
- Solicitação de obtenção: a solicitação enviada quando as cópias do consumidor e do seguidor precisam ler a mensagem do corretor.
Aqui, devemos notar que ambas as solicitações acima devem ser enviadas para a cópia líder da partição.
Pergunta 1: E se um corretor receber uma solicitação para uma partição específica, mas o líder da partição estiver em outro corretor ?
Resposta: Então, o cliente que enviou a solicitação receberá uma resposta de erro "líder de partição não".
Portanto, o cliente Kafka precisa ser responsável por enviar a solicitação ao corretor correto.
Questão 2: Como o cliente sabe para onde enviar a solicitação?
Resposta: O cliente usa o tipo de solicitação da solicitação de metadados .
O conteúdo da solicitação inclui uma lista de tópicos nos quais o cliente está interessado. Geralmente, a mensagem de resposta do lado do servidor especificará as partições incluídas no tópico, a distribuição das partições, qual cópia é a líder e assim por diante.
Além disso, as solicitações de metadados podem ser enviadas a qualquer broker, porque todos os brokers armazenaram essas informações em cache.
Pedido de produção
Olhando para o conteúdo anterior, o produtor tem uma configuração de parâmetro chamada acks
- acks = 1: Enquanto o líder receber a mensagem, a mensagem é considerada escrita com sucesso.
- acks = all: Todas as réplicas sincronizadas precisam receber a mensagem para serem consideradas bem-sucedidas.
- acks = 0: Depois que o produtor envia uma mensagem, não há necessidade de esperar a resposta do corretor.
Então, quando o corretor contendo uma cópia do líder recebe uma solicitação de produção, ele executará as seguintes etapas para a solicitação:
- Verificação de permissão: O usuário que envia os dados tem permissão para escrever o assunto?
- Verificação de parâmetro: o valor de acks é válido? (Apenas 0, 1, todos)
- Verificação da réplica: Se acks = all, há réplicas sincronizadas suficientes para garantir que a mensagem foi gravada com segurança? (Se o número for insuficiente, Kafka pode se recusar a escrever)
- Gravação da mensagem: gravar no disco local.
- Verifique os parâmetros: Após a mensagem ser gravada no líder da partição , verifique o parâmetro acks. Se acks = 0 ou 1, o corretor retorna uma resposta imediatamente. Se acks = all, salve a solicitação em um buffer do purgatório , até que o líder descubra que todas as cópias do seguidor copiaram a mensagem, a resposta será retornada ao cliente.
Obter pedido
A maneira como o broker processa solicitações de busca é muito semelhante à maneira de produzir solicitações. Em uma frase: O cliente envia uma solicitação ao corretor para uma mensagem com um deslocamento específico na partição do tópico.
Coloque a imagem primeiro: as
etapas gerais são:
- A solicitação é enviada ao líder da partição designada e, em seguida, o cliente consulta os metadados para garantir que a rota solicitada está correta.
- Verifique se a solicitação é válida: se o deslocamento existe na partição, etc.
- Se o deslocamento solicitado existir, o corretor lê a mensagem da partição de acordo com o limite superior do número especificado pelo cliente e a devolve ao cliente.
Há vários pontos a serem observados aqui:
1. O Kafka usa tecnologia de cópia zero para enviar mensagens ao cliente: ou seja, a mensagem é enviada diretamente do arquivo para o canal da rede sem passar por nenhum buffer intermediário.
2. O cliente Kafka geralmente define os limites superior e inferior dos dados retornados pelo corretor para controlar a quantidade de dados retornados pelo corretor de uma vez.
3. Ou seja, se a quantidade de dados não atingir o limite inferior, após o envio da solicitação da corretora, a mensagem não será recebida até que a quantidade de dados seja suficiente.
4. Claro, o cliente não vai esperar que o corretor acumule dados por um determinado período de tempo. Se o volume de dados ainda não atender ao padrão, os dados serão retornados.
- Os dados retornados são dados síncronos.
Armazenamento físico
A unidade básica de armazenamento do Kafka é uma partição. Quando o Kafka é configurado, um endereço de diretório para a partição de armazenamento é geralmente especificado, que é o parâmetro log.dirs (server.properties, tome cuidado para não confundi-lo com log.properties)
A seguir, veremos como Kafka realiza a alocação de partição e armazenamento de dados.
Alocação de partição
Quando o Kafka criar um tópico, ele decidirá como alocar partições entre os corretores.
Exemplo: temos 6 corretores, planejamos criar um tópico com 10 partições e o fator de replicação é 3 (a quantidade de cópia), então haverá um total de 10 * 3 = 30 cópias de partição, que serão alocadas para 6 corretores. Ao realizar a alocação de partição, o Kafka precisa exigir o seguinte:
- As cópias da partição são distribuídas uniformemente nos brokers. (Equivalente a uma média de 5 cópias de partição para cada corretor)
- Certifique-se de que diferentes cópias de cada partição sejam distribuídas em diferentes brokers. (Cada partição tem 3 cópias, incluindo uma cópia master e uma cópia secundária), o que significa que as cópias master e slave precisam ser alocadas em brokers diferentes e várias cópias da mesma partição não podem estar no mesmo broker. Consulte a imagem abaixo
Gerenciamento e indexação de arquivos
Existem duas maneiras de gerenciar arquivos no Kafka: tempo de armazenamento e tamanho do armazenamento. Para obter detalhes, consulte os parâmetros do artigo do produtor.
Geralmente, Kafka divide a partição em vários fragmentos. ** Por padrão, cada fragmento contém 1 GB ou uma semana de dados, e o menor deve prevalecer. ** Quando o broker grava dados na partição, se o limite do fragmento for atingido, o arquivo atual é fechado e um novo arquivo é aberto.
O segmento que está gravando dados atualmente é chamado de segmento ativo e o segmento ativo nunca será excluído.
Então, qual é o formato do arquivo escrito?
Sabemos que o Kafka salva a mensagem e o deslocamento em um arquivo, então o que mais o arquivo contém?
Além de pares de valores-chave e deslocamentos, a mensagem também contém o tamanho, a soma de verificação, o número da versão do formato da mensagem, o algoritmo de compactação (Snappy, Gzip, Lz4) e o carimbo de data / hora da mensagem. O carimbo de data / hora se refere à hora em que a mensagem chega ao broker. Mas você pode notar que o canto inferior direito da imagem acima está preto, o que significa que o produtor envia uma mensagem compactada. , O mesmo lote de mensagens será compactado e enviado como mensagens compactadas.
Use uma ferramenta que vem com o Kafka para ver o conteúdo do fragmento (conteúdo da mensagem)
./bin/kafka-run-class.sh kafka.tools.DumpLogSegments --deep-iteration 文件
Os consumidores podem começar a ler mensagens de qualquer offset disponível em Kafka, então como os consumidores o localizam?
Resposta: Use o índice.
O Kafka mantém um índice para cada partição, que mapeia o deslocamento para o arquivo de fragmento e a posição do deslocamento no arquivo. Obviamente, o índice também será dividido em fragmentos, portanto, ao excluir uma mensagem, o índice correspondente também será excluído.
Limpeza de arquivos e princípio de funcionamento
Cada fragmento de log de Kafka pode ser dividido em duas partes.
- Parte limpa: essas mensagens foram limpas antes e cada chave tem apenas um valor correspondente, que é retido durante a última limpeza.
- A parte suja: Essas mensagens são dados gravados após a última limpeza.
Como mostrado:
O Kafka pode configurar sua própria função de limpeza (log.cleaner.enabled). Se iniciado, cada corretor iniciará um encadeamento do gerenciador de limpeza e vários encadeamentos de limpeza. Os encadeamentos de limpeza são responsáveis por realizar as tarefas de limpeza. Eles selecionarão a taxa de poluição (sujo mensagem A partição com a maior proporção do tamanho total da partição) é limpa.
O thread de limpeza criará um mapa na memória. Cada elemento neste mapa contém o valor hash e o deslocamento da chave da mensagem. O valor hash da chave é 16B, e o deslocamento é 24B no total. Portanto, se você quiser limpar um fragmento de log de 1 GB, supondo que o tamanho de cada mensagem seja 1 KB, esse fragmento contém um milhão de mensagens e só precisamos de um mapa de 24 MB para limpar esse fragmento, o que é muito eficiente.
Princípio de funcionamento aproximado :
- Depois que o encadeamento de limpeza cria o mapa de deslocamento, ele começa a ler a mensagem do fragmento mais limpo, que é a mensagem mais antiga, e compara seu conteúdo com o conteúdo do mapa.
- Verifique se a chave da mensagem existe no mapa. Se não existir, significa que o valor da mensagem é o mais recente e a mensagem será copiada para o fragmento substituído. Se existir, a mensagem será ignorada.
- Após copiar todas as mensagens, trocamos o fragmento de substituição pelo fragmento original e, em seguida, iniciamos a limpeza do próximo fragmento.
- Após completar todo o processo de limpeza, cada chave corresponde a uma mensagem diferente (o valor da mensagem é o mais recente), a imagem é a seguinte:
O acima pode ser resumido de uma forma pequena, nós manteremos apenas uma mensagem recente para cada chave.
Pergunta 1: Mas o que devo fazer se precisar excluir todas as mensagens correspondentes a uma determinada chave. (Por exemplo, um usuário não usa mais um determinado serviço e precisa excluir todas as mensagens do cliente)
Resposta:
1. Para excluir completamente uma chave do sistema, o aplicativo deve enviar uma mensagem contendo a chave com o valor nul.
2. Quando o encadeamento de limpeza encontrar a mensagem, ele executará uma limpeza regular primeiro e manterá apenas a mensagem cujo valor é nulo. A mensagem com valor nulo, que chamamos de mensagem de marca para exclusão , será mantida por um período de tempo.
3. Durante esse período, o consumidor pode ver a mensagem de marca para exclusão, mas descobriu que seu valor foi excluído.
4. Após esse período, o tópico de limpeza removerá a mensagem de marca para exclusão e a chave correspondente também será excluída da partição Kafka.
Pergunta 2: Por que a mensagem da marca para exclusão é retida por um curto período de tempo?
Resposta: 1. Em primeiro lugar, o tempo de retenção pode ser configurado.
2. Em segundo lugar, o tempo de retenção é configurado para permitir que os consumidores vejam a mensagem de marca de exclusão durante este período, para que os consumidores entendam que o valor desta mensagem foi excluído e os consumidores profissionais vão entender: Oh, esta mensagem não é mais útil agora , todas as mensagens relevantes precisam ser excluídas do banco de dados.
Resumindo
Este artigo descreve os seguintes aspectos:
- Membro do cluster e controlador.
- Processo de replicação e processamento de pedidos de Kafka.
- Armazenamento e formato de arquivo de Kafka, princípio de compensação.
O próximo artigo vai falar sobre a transmissão confiável de dados de Kafka.