o problema
Antes do Chubby, os sistemas do Google elegiam primário de dois jeitos ruins. Quando duplicar trabalho não fazia mal, cada equipe inventava seu método ad hoc. Quando a correção importava, alguém acordava um operador. Eleger primário entre pares é consenso distribuído sobre rede assíncrona, e isso o Paxos resolve — o Google até mantinha uma biblioteca cliente de Paxos, independente do Chubby. Só que usar essa biblioteca exige que o serviço seja escrito como máquina de estados replicada, e serviços reais nascem como protótipo sem plano de disponibilidade. A replicação entra depois, num código que não foi estruturado para ela, muitas vezes sem poder quebrar compatibilidade durante a transição.
O segundo problema era anunciar o resultado. Eleito o primário, os milhares de processos que dependem dele precisam descobrir quem venceu. A ferramenta óbvia, DNS, tem cache baseado em tempo: um TTL curto o suficiente para trocar um servidor morto rápido gera carga absurda. Um job de três mil processos em que todos falam com todos, com TTL de 60s, pediria 150 mil lookups por segundo — e um servidor DNS Xeon de dois núcleos a 2,6 GHz atendia cerca de 50 mil. A variabilidade da carga de DNS já era um problema sério no Google antes do Chubby existir.
a ideia
Em vez de distribuir o consenso, centralize-o num serviço confiável e venda locks. Trocar um servidor comum em servidor eleito passa a custar duas linhas: adquira o lock para virar master, passe o contador de aquisição junto com a RPC de escrita, e faça o destino rejeitar escritas com contador antigo. Programador nenhum precisa aprender Paxos — precisa reconhecer um lock, coisa que ele acha que já sabe usar (e o paper observa que ele geralmente está errado).
Junto vem uma segunda decisão: servir arquivos pequenos. O primário eleito escreve a própria identidade no arquivo do lock, e quem procura por ele lê ali. Isso evita depender de um segundo serviço de nomes e reaproveita a consistência do mesmo protocolo. E há uma inversão de responsabilidade escondida no quorum: uma célula do Chubby usa cinco réplicas, três precisam estar de pé — mas um cliente sozinho, com um único processo vivo, consegue segurar o lock e progredir com segurança. O serviço funciona como eleitorado emprestado.
como funciona
Uma célula tem cinco réplicas em racks distintos. Elas elegem um master por consenso, com promessa de não eleger outro durante o master lease, de alguns segundos. Só o master lê e escreve o banco; escritas viram consenso e são confirmadas quando alcançam a maioria; leituras o master responde sozinho, seguro porque enquanto o lease vale nenhum outro master pode existir.
A interface é um sistema de arquivos podado: árvore estrita, sem link, sem rename entre diretórios, sem tempo de último acesso, permissão só do próprio nó — tudo isso para permitir particionar o namespace por diretório mais tarde. Nós são permanentes ou efêmeros, e o nó efêmero some quando ninguém o mantém aberto, o que serve de sinal de vida. Qualquer nó é um lock reader-writer advisory: segurar o lock F não impede ninguém de ler o arquivo F.
O cliente mantém uma sessão viva por KeepAlives. O master segura a RPC até o lease anterior estar perto de vencer e só então responde com o novo prazo, 12s por padrão, esticável para uns 60s quando ele está sobrecarregado. Eventos e invalidações de cache pegam carona nessa resposta, o que garante que ninguém renove sessão sem confirmar invalidação e faz todo tráfego fluir do cliente para o master. O cliente mantém uma estimativa conservadora do prazo; quando ela vence, ele esvazia o cache e entra em jeopardy por um grace period de 45s, bloqueando as chamadas da aplicação até saber se a sessão sobreviveu. O novo master escolhe um epoch novo, rejeita chamadas com epoch velho, reconstrói sessões e locks do banco e só depois libera as operações.
O cache é write-through, consistente, mantido por invalidação — nunca por atualização, porque protocolo que só atualiza pode mandar update para sempre a um cliente que leu uma vez. O banco começou como Berkeley DB replicado e virou um WAL com snapshot escrito em casa: o código de replicação do Berkeley DB era novo demais para o risco. O snapshot vai para um servidor GFS em outro prédio, para não criar dependência cíclica com uma célula que pode precisar do Chubby para eleger o próprio master.
o que isso custou
O master é único por célula, e a máquina dele é igual à dos clientes. Perto da sobrecarga — tipicamente acima de 90 mil sessões — a latência dispara e sessões caem. Escrita leva 5 a 10 ms a mais pelo log, e até dezenas de segundos se um cliente recém-morto tinha aquele arquivo em cache. O código de fail-over, exercitado raramente, foi descrito pelos próprios autores como fonte rica de bugs interessantes. Em algumas dezenas de anos-célula, dados foram perdidos seis vezes: quatro por bug do banco, duas por erro de operador, nenhuma por hardware — e os erros de operação aconteceram durante upgrades feitos para corrigir os bugs.
Sem quota, um módulo de rastreio de uploads passou a reescrever um arquivo de 1,5 MB inteiro a cada ação de usuário, consumindo mais espaço que todos os outros clientes somados; o limite de 256 kB veio depois, e a migração levou cerca de um ano. Desenvolvedores tratam o serviço como sempre disponível: houve quem derrubasse centenas de máquinas em recuperação de dezenas de minutos ao receber o evento de fail-over. A biblioteca cliente em C++ tem 7 mil linhas e ninguém quis reescrevê-la em Java, então virou mais um servidor de conversão de protocolo. E os KeepAlives tiveram de sair de TCP para UDP, porque o back-off do TCP ignora prazos de nível mais alto e derrubava sessões sob congestionamento.
Duas admissões honestas fecham a conta. O paper diz de saída que não é pesquisa e não propõe algoritmo novo. E o servidor de locks finos que eles projetaram para clientes nunca precisou ser escrito: quem otimiza a aplicação acaba removendo comunicação, e removendo comunicação acaba em lock grosseiro.
onde isso aparece hoje
O Google File System usa um lock do Chubby para nomear o master. O Bigtable o usa três vezes: elege master, deixa o master descobrir os servidores que controla e deixa clientes acharem o master. O MapReduce o usa como ponto de encontro. Nos dois primeiros, o Chubby também guarda a raiz da estrutura de dados distribuída — a metadata pequena de onde tudo o mais pende.
O padrão de embrulhar Paxos num serviço com interface de arquivo, sessões e watches saiu do Google: o ZooKeeper e, mais tarde, o etcd ocupam esse lugar em pilhas abertas, com a mesma divisão entre um quorum pequeno e muitos clientes que só querem saber quem manda agora.