antonio leandro

sistemas distribuídos

In Search of an Understandable Consensus Algorithm

paper · núcleo · Diego Ongaro, John Ousterhout · · ~64 min de leitura do original

a tese

compreensibilidade dá para tratar como requisito de projeto: com líder forte e menos estado não-determinístico, raft entrega o mesmo que o multi-paxos usando só quatro tipos de mensagem

o que fica

  1. Um líder do Raft nunca declara commit de uma entrada de termo anterior contando réplicas: só entradas do termo corrente são commitadas por maioria, e as anteriores entram de carona pela propriedade de Log Matching.
  2. Aleatorizar o election timeout resolve split vote melhor que ranquear candidatos: sem aleatoriedade a eleição passava de 10 segundos nos testes, e com intervalo de 150 a 300ms o líder volta em centenas de milissegundos.
  3. A restrição de voto substitui todo um mecanismo de recuperação: como o eleitor nega voto a candidato com log menos atualizado que o seu, o novo líder já nasce com todas as entradas commitadas e nunca precisa recebê-las de ninguém.
  4. Segurança no Raft não depende de relógio; disponibilidade depende. A única exigência temporal é broadcastTime muito menor que electionTimeout, que por sua vez é muito menor que o MTBF dos servidores.
  5. Trocar a configuração do cluster direto de Cold para Cnew é inseguro porque os servidores trocam em instantes diferentes e duas maiorias disjuntas podem eleger dois líderes no mesmo termo.
  6. O líder forte fecha a porta para otimizações: o EPaxos, sem líder, consegue latência menor em WAN explorando comutatividade de comandos, e o Raft abre mão disso em nome do algoritmo mais simples.

o problema

Consenso é o que permite que um punhado de máquinas se comporte como uma máquina só, confiável, mesmo quando algumas caem. Por uma década, consenso significou Paxos: era o protocolo ensinado nos cursos e o ponto de partida de quase toda implementação. O problema é que quase ninguém entende Paxos. Os próprios autores contam que só compreenderam o protocolo completo depois de ler várias explicações simplificadas e projetar um protocolo alternativo — um processo que levou quase um ano. Numa enquete informal com participantes do NSDI 2012, eles encontraram poucas pessoas confortáveis com Paxos, inclusive entre pesquisadores experientes.

O segundo problema é pior para quem constrói sistemas: não existe um algoritmo multi-Paxos amplamente aceito. Lamport descreveu bem o caso de uma única decisão e esboçou como compor várias, deixando os detalhes de fora. Cada implementação começa em Paxos, esbarra nas lacunas e termina numa arquitetura significativamente diferente. Os implementadores do Chubby escreveram que há lacunas expressivas entre a descrição do algoritmo e a necessidade de um sistema real, e que o sistema final se baseia num protocolo não provado. Se o código não parece com o paper, a prova de correção do paper não vale muito para o código.

a ideia

Ongaro e Ousterhout inverteram a ordem dos requisitos. Correção e eficiência continuaram obrigatórias, mas o objetivo principal virou compreensibilidade: sempre que havia duas alternativas de projeto, ganhava a mais fácil de explicar e de raciocinar a respeito. Isso levou a duas técnicas repetidas. Decompor: eleição de líder, replicação de log, segurança e mudança de configuração viram problemas separados, que dá para entender um de cada vez. E reduzir o espaço de estados: log não pode ter buracos, e o número de maneiras de dois logs discordarem é limitado por construção.

A consequência estrutural é o líder forte. Em Paxos, eleger líder é otimização de desempenho, ortogonal ao consenso. No Raft, a eleição é a primeira das duas fases do consenso, e entrada de log só flui numa direção: do líder para os followers.

como funciona

O tempo é dividido em termos numerados, cada um começando com uma eleição. O termo funciona como relógio lógico: todo RPC carrega o termo do remetente, e quem descobre que está atrasado vira follower na hora. Cada servidor é leader, follower ou candidate. O algoritmo básico precisa de dois RPCs: RequestVote e AppendEntries, esse último servindo também de heartbeat.

Se um follower fica sem notícias por um election timeout, ele incrementa o termo, vota em si e pede votos. Ganha quem juntar maioria do cluster. Os timeouts são sorteados num intervalo fixo, então em geral um servidor sozinho estoura primeiro, vence e manda heartbeat antes dos outros acordarem.

Na replicação, o líder anexa o comando ao próprio log e manda AppendEntries com o índice e o termo da entrada imediatamente anterior. O follower recusa se não tiver essa entrada — é a consistency check, e ela vale como passo de indução: se ela passa, os dois logs são idênticos até ali. Quando recusa, o líder decrementa o nextIndex daquele follower e tenta de novo, até achar o ponto de acordo; dali para a frente o log do follower é sobrescrito. O líder nunca apaga nada do próprio log.

A segurança vem de uma restrição no voto: o eleitor nega voto a quem tem log menos atualizado que o seu, comparando termo e depois comprimento da última entrada. Como o candidato precisa de maioria, e toda entrada commitada está em maioria, o vencedor tem tudo que foi commitado.

Reconfiguração usa consenso conjunto: uma entrada de log Cold,new em que as decisões exigem maioria nas duas configurações ao mesmo tempo. Só depois que ela commita é que entra o Cnew. Servidores novos entram antes como membros sem voto, para não travar commits enquanto se atualizam. E, para não serem derrubados por servidores removidos que continuam pedindo eleição, os servidores ignoram RequestVote recebido dentro do timeout mínimo desde o último contato com o líder.

Log não cresce para sempre: cada servidor faz snapshot do próprio estado, guardando último índice e termo incluídos, e o líder usa um terceiro RPC, InstallSnapshot, para followers muito atrasados.

o que isso custou

A regra de commit é deliberadamente conservadora. Existem casos em que dá para concluir com segurança que uma entrada antiga está commitada, e o Raft não os aproveita: prefere a regra única e simples de contar réplicas só do termo corrente.

O snapshot rompe o próprio princípio do líder forte, já que followers comprimem sozinhos, sem o líder saber. Os autores defendem a exceção argumentando que o consenso já foi alcançado quando se faz snapshot, então não há decisão em conflito.

O líder forte também impede otimizações. O EPaxos, sem líder, commita em uma rodada quando os comandos concorrentes comutam e distribui melhor a carga — ao custo de complexidade significativa. Batching e pipelining são citados como fáceis de aplicar no Raft, mas ficaram como trabalho futuro.

A verificação formal é parcial: a especificação em TLA+ tem cerca de 400 linhas, a Leader Completeness foi provada mecanicamente, mas essa prova depende de invariantes não checados mecanicamente, e a prova da State Machine Safety é informal, com cerca de 3.500 palavras. O estudo com usuários também tem limites que os autores reconhecem: 15 dos 43 participantes já tinham alguma experiência com Paxos, a diferença média foi de 4,9 pontos em 60 (25,7 contra 20,8), e a preferência declarada — 33 de 41 achando Raft mais fácil de implementar e de explicar — pode ter sido enviesada por conhecerem a hipótese do estudo.

onde isso aparece hoje

Raft virou o algoritmo padrão para quem precisa de um log replicado e não quer reinventar multi-Paxos. Na época do paper já havia cerca de 25 implementações independentes de código aberto; hoje etcd, Consul e TiKV são os exemplos mais conhecidos, e o TiDB descreve o próprio armazenamento como Raft-based no título. O contraste é com o lado Paxos da família: o Paxos Made Simple continua sendo a referência teórica, e sistemas como o Chubby e o Spanner dizem se basear em Paxos sem publicar o algoritmo em detalhe — que é exatamente a lacuna que motivou este paper.

lido na íntegra por pipeline de llm, revisado por antonio leandro antes de publicar ·