Entendendo o protocolo Raft

If you’re thinking without writing, you only think you’re thinking.
Leslie Lamport (criador do Paxos e do LaTeX)
Há duas razões evidentes para distribuir computação em diversas unidades de execução (nós). A primeira delas é suportar workloads maiores. A segunda, é garantir disponibilidade. Entretanto, distribuir computação faz emergir categorias inéditas de problemas. Dentre elas, talvez uma das mais desafiadoras é garantir consenso.
0
Considerações?x

Neste capítulo apresento um protocolo chamado Raft. Uma solução possível para o problema de garantir consenso entre unidades de processamento em sistemas distribuídos.

Definição: Protocolo

Característica do que segue normas rígidas de procedimento; formalidade, etiqueta. Em arquitetura de software, conjunto de comportamentos que componentes se “comprometem” a cumprir, independente de tecnologia, design ou implementação.

O que é “consenso” e por que é importante

Imagine-se desenvolvendo um sistema que necessite um componente para “contar acessos” realizados em determinadas páginas de um site

Em termos simples, a demanda funcional (contar acessos) poderia ser atendida facilmente com uma “unidade de processamento” (servidor físico, virtual, contêiner ou, até mesmo, uma função)  rodando código simples, que mantem um dicionário em memória (ou em disco) onde a chave seria o id do recurso e o valor seria a contagem atual de acessos. Essa solução, entretanto, dificilmente atenderia demandas de disponibilidade, tampouco resiliência.
0
Considerações?x
Demandas por disponibilidade e resiliência geralmente são atendidas mediante adição de recursos redundantes.

A solução evidente para melhorar tais atributos é ponderar sobre a adição de mais “unidades de processamento”. Entretanto, daí nasce a dificuldade de garantir que todas mantenham o mesmo estado (em nosso exemplo, entradas e valores no dicionário).  Ou melhor, que todas as unidades “concordem” sobre quais são os valores atualizados. Ou seja, as “unidades de processamento” precisam manter consenso.

Sem consenso, não seria possível cumprir o objetivo funcional.

Em aplicações data centric é comum “transferir a responsabilidade” de garantir consenso para bancos de dados operando em cluster (para garantir confiabilidade).

O que é o Raft

Raft é um protocolo que, corretamente implementado, garante consenso em sistemas distribuídos. Ele foi desenvolvido como uma alternativa mais fácil de entender e implementar ao Paxos – outro protocolo, desenvolvido por Leslie Lamport, que ainda é um padrão de facto.

Raft, In Search of an Understandable Consensus Algorithm

Excelente palestra ministrado pelos criadores do Raft, detalhando o funcionamento do protocolo.

Acessar vídeo

Raft, assim como Paxos, habilita a aplicação de uma técnica conhecida como State Machine Replication que permite a conversão de algoritmos em versões distribuídas, tolerantes a falhas.

Implementing Fault-tolerant services using the State Machine Approach: a tutorial

Fred Schneider compartilha nesse artigo uma abordagem geral para conversão de serviços em máquinas de estado que, por sua vez, podem ser distribuídas, viabilizando o desenvolvimento de serviços tolerantes a falhas.

Acessar artigo

Generalizando serviços como máquinas de estado

Uma generalização necessária para entender todo o “poder” do Raft é considerar qualquer serviço como uma máquina de estados – que mantem um estado atual, internamente – e responde a estímulos externos. Dessa forma, a replicação de um serviço pode ser interpretada, então, como a replicação da máquina de estados (com seu estado).

As alterações de estado na máquina, acontecem pela execução de comandos. A replicação do estado acontece pela replicação do log dos comandos para que estes possam ser executados, em todas as instâncias, em uma mesma ordem.

Conceitos fundamentais do Raft

Raft entende que há consenso quando a maioria simples de “unidades de processamento” cooperando (por exemplo, 3 nós em um cluster com 5) em determinado trabalho “concordam em aceitar” uma demanda. No exemplo indicado anteriormente, uma “atualização” no contador de acessos a um recurso seria “globalmente aceita” quando houvessem evidências de que ela pode ser aplicada na maioria simples dos nós.

A “orquestração” do trabalho, em um cluster operando Raft, é garantida por um nó operando como líder (leader), enquanto os demais operam como seguidores (followers). Todas as demandas de trabalho para o cluster são sempre realizadas através do nó-líder, ou encaminhadas para ela quando recebidas por um nó-seguidor.

Caso o nó-lider fique, por alguma razão, indisponível, ocorre a eleição de outro nó do cluster para esta função. Idealmente, todos os nós devem ter condições (implementação) de assumir a liderança. De qualquer forma, para que um nó se converta em líder, deve-se lançar como candidato.

O nó-lider mantem comunicação contínua, em intervalos regulares, com todos os nós-seguidores (heartbeat). O intuito é garantir que o “líder vive”.

Um nó-seguidor lança-se candidato sempre que ficar “tempo demais” sem receber notificações do nó-líder. Quando isso acontece, ele assume que o nó-líder está indisponível e assume que seu mandato (term) chegou ao fim. Envia, então, solicitações de votos a todos os nós do cluster e considera-se eleito caso receba confirmação da maioria simples.

O tempo em que um nó ocupa a liderança é considerado seu “mandato” (term). Os mandatos no cluster são identificados através de um contador incremental, atualizado sempre que um nó lança-se candidato.

Um nó-seguidor concordará em votar em outro nó, para assumir a liderança, quando 1) não estiver mais recebendo mensagens do nó-líder com mandato em vigência; 2) ele mesmo não tiver se lançado candidato; 3) ainda não tiver “votado” no term especificado no pedido de voto que recebeu.

Um nó-candidato que não receber votos suficientes (maioria simples) durante um período razoável (election timeout) pode iniciar uma nova campanha, incrementando o term, caso não tenha ainda sido contatado por un novo nó-líder.

Por todo o exposto, entende-se então que cada nó em um cluster operando Raft pode assumir um dos seguintes três papéis: líder, seguidor, candidato.

Arquitetura (proposta) de um “nó” Raft

Cada nó em um cluster Raft possuirá a implementação de dois serviços e uma estrutura de dados.

O primeiro serviço, um motor de consenso, é o responsável pela implementação do protocolo para relacionamento com outros nós e a atualização do log.

O log é uma estrutura de dados, implementada em sua forma mais simples como uma lista encadeada, que relaciona todos os comandos commited que devem ser processados pela máquina de estados.

O segundo serviço, a máquina de estados, é quem, efetivamente, processa os comandos relacionados no log.

A eleição do líder (leader election)

Todo nó em um cluster assume o status de follower por padrão.

Quando um follower fica tempo suficiente sem receber quaisquer mensagens de um leader (election timeout, randomizado entre 150ms e 300ms), alterna imediatamente seu estado para candidate e passa a solicitar votos para os demais participantes tentando iniciar um novo mandato (election term).

Um nó converte-se em líder quando recebe a maioria simples (número de nós, mais um [incluindo o dele]) de votos positivos dos participantes do cluster.

Se um número suficiente de votos não for obtido em tempo razoável (election timeout), o nó abandona sua candidatura.

O processo que define um líder para o cluster é conhecido como leader election.

Replicando dados (log Replication)

O funcionamento de um cluster Raft pode ser descrito como segue:

  1. Todo comando recebido por um nó Raft, a partir de um cliente, é encaminhado para processamento pelo motor de consenso do nó-líder que o adiciona ao seu log em estado uncommited.
  2. O nó-servidor envia entradas uncommited para que sejam replicadas nos logs dos nós-seguidores, também como uncommited.
  3. Os nós-seguidores confirmam para o nó servidor o recebimento e a adição do comando em seus logs
  4. O nó-servidor, ao receber confirmação da maioria simples dos nós-seguidores, muda o estado do comando, no log, para commited.
  5. Cada nó-seguidor atualiza o estado do comando, no log, para commited
  6. As máquinas de estado, em cada nó, processam comandos, ainda não processados, que estejam em estágio commited.
  7. O nó-servidor, retorna sucesso para o cliente.

Caso o nó-líder não receba confirmações suficientes para um comando, ele é removido do log.

The Secret Lives of Data - Raft

Ben Johnson conseguiu criar uma visualização tremendamente amistosa para como Raft funciona – gráfica e interativa. Vale a pena!

Acessar artigo

Recuperando-se de partições de rede (network partitions)

Quando, eventualmente, ocorrer uma partição na rede do cluster (como, por exemplo, quando os nós encontram-se em dois datacenters separados), eventualmente poderá ocorrer uma nova eleição em uma das participações e, inclusive, a eleição de um novo líder caso existam elementos suficientes para obtenção de maioria simples.

A liderança com a partição com menos elementos não será capaz de aceitar alterações em função de não possuir maioria simples para que ocorra o commit. Já a liderança com a maioria poderá aceitar atualizações sem restrições.

Ao se desfazer a partição, o antigo líder receberá indicativo da presença de um novo líder com um “mandato” mais recente e deverá abdicar de sua posição.

Para pensar…

Construir sistemas escaláveis, disponíveis, confiáveis e resilientes não é tarefa simples. Invariavelmente, o projeto de tais sistemas demanda abordagens distribuídas que apresentam uma série de desafios difíceis de superar, com destaque para a gestão de consenso.

Em boa parte das situações, a gestão do consenso é obtida pela utilização de algum mecanismo de armazenamento – como banco de dados – distribuído. Entretanto, essa não precisa e nem deveria ser a única abordagem.

A utilização de estruturas de dados como quadtrees, por exemplo, tão úteis para serviços baseados em localização, é consideravelmente mais fácil em memória, logo pela adoção de um protocolo como Raft (ou Paxos).

É provável que você não precise implementar, nunca, protocolos de consenso. Entretanto, é bom saber como eles funcionam para saber que há uma alternativa quando você, eventualmente, precisar dela (há muito mais no mundo do que persistência em bancos de dados).
0
Considerações?x

Referências bibliográficas

NGARO, Diego; OUSTERHOUT, John. The Raft Consensus Algorithm. Disponível em: https://raft.github.io/. Acesso em: 28 jun. 2022.

Compartilhe este capítulo:

Compartilhe:

Comentários

Participe da construção deste capítulo deixando seu comentário:

Inscrever-se
Notify of
guest
0 Comentários
Feedbacks interativos
Ver todos os comentários

AUTOR

Elemar Júnior

Fundador e CEO da EximiaCo, atua como tech trusted advisor ajudando diversas empresas a gerar mais resultados através da tecnologia. 

Mentorias

para arquitetos de software

Imersão, em grupo, supervisionada por Elemar Júnior, onde serão discutidos tópicos avançados de arquitetura de software, extraídos de cenários reais.

Consultoria e Assessoria em

Arquitetura de Software

EximiaCo oferece a alocação de um Arquiteto de Software em sua empresa para orientar seu time no uso das melhores práticas de arquitetura para projetar a evolução consistente de suas aplicações.

Podcast

Arquitetura de Software Online

55 51 9 9942 0609  |  me@elemarjr.com

+55 51 99942-0609 |  contato@eximia.co

+55 51 99942-0609  contato@eximia.co

0
Quero saber a sua opinião, deixe seu comentáriox
()
x