Jepsen: TigerBeetle 0.16.11
(jepsen.io)- TigerBeetle é um banco de dados OLTP especializado em contabilidade de partidas dobradas, desenvolvido com foco em segurança e alta velocidade de processamento
- Suporta o protocolo de consenso Viewstamped Replication e o critério de strong serializability, com uma arquitetura otimizada para cargas de alta contenção e alto throughput
- Conta com um projeto e procedimentos de teste fortemente voltados para tolerância a falhas e resiliência a indisponibilidades, buscando operar sem perda de dados em diversos cenários de falha
- Os testes do Jepsen encontraram diversos bugs e problemas de desempenho em upgrades, testes, modelo operacional e resiliência do cluster, melhorando a capacidade de resposta a esses problemas
- Na versão mais recente, há várias melhorias e correções de bugs em desempenho de replicação baseada em Ring, tratamento de erros do cliente e precisão de logs e consultas
Introdução ao TigerBeetle
- TigerBeetle é um banco de dados de processamento de transações online (OLTP) especializado em contabilidade de partidas dobradas (Double-entry bookkeeping)
- Garante strong serializability com base no protocolo de consenso Viewstamped Replication (VR) e armazena apenas dados de contas e transferências entre contas
- É adequado para ambientes com alto volume de transações e forte concorrência, como switches internos de bancos, corretagem, emissão de ingressos e medição de energia
- Sua arquitetura concentra todas as operações de escrita em um único nó (Core), priorizando scale-up em vez de scale-out
- Busca maximizar o throughput em um único nó com otimizações amigáveis ao hardware, como processamento em lote, paralelismo de IO e esquema fixo
Resiliência a falhas e tolerância a defeitos
- O TigerBeetle fornece modelos explícitos e procedimentos de recuperação para falhas de memória, processo, relógio, armazenamento e rede
- A durabilidade dos dados garante ausência de perda de dados mesmo que apenas uma réplica permaneça viva
- Se os registros forem corrompidos em todas as réplicas, o sistema para de forma segura
- Assume diversos tipos de falhas, como problemas de hardware/software do sistema, desvios de relógio, corrupção de disco, latência, perda e duplicação na rede
- Aplica Viewstamped Replication, técnicas de Protocol-Aware Recovery, checksums em blocos de dados e armazenamento em múltiplas réplicas
- Usa verificação em tempo de execução (assertion) para minimizar impactos quando ocorrem erros e bugs
Forma de upgrade
- O binário inclui o código da versão atual e de várias versões anteriores
- O upgrade pode ser feito simplesmente substituindo o binário
- Todos os nós do cluster mudam de versão automaticamente em modo rolling, com mínima intervenção do usuário
- Ao evitar que operações commitadas em uma versão sejam commitadas em duplicidade em outra, favorece a prevenção de inconsistências de estado
Modelo de tempo
- Usa simultaneamente relógios lógicos baseados em views VR e números de operação e relógios físicos híbridos (physical time)
- O líder coleta o horário POSIX de todas as réplicas e sincroniza o cluster mutuamente dentro de uma margem de erro
- Se a sincronização dos relógios falhar por mais de 60 segundos, o serviço é recusado
- Os timestamps usam a unidade de "nanossegundos desde a época Unix", mas há um desvio de 27 segundos em relação ao tempo POSIX real
- Em ajustes de leap second ou ajustes negativos de tempo, o relógio interno pode desacelerar
Modelo de dados
- Suporta apenas dois tipos de dados: conta (account) e transferência (transfer)
- Cada campo tem tamanho fixo, segue o princípio de imutabilidade e é baseado em unsigned int
- A conta é definida por id de 128 bits definido pelo usuário, ledger, flags, horário de criação e campos customizados
- A transferência inclui debit/credit account id, code, amount e campos customizados
- A transferência pode ser executada imediatamente (etapa única) ou em duas etapas (reserva e liquidação negociada)
- Transferências pendentes (
pending) podem ser canceladas ou expirar - Transferências especiais podem ser usadas para fechar ou reabrir contas
- Transferências pendentes (
Modelo operacional e transações
- O cliente opera em unidades de uma única requisição (batch) para atualizar ou consultar o estado dos dados
- Cada evento dentro da requisição é processado sequencialmente como uma transação atômica (atomic)
- Não há suporte para reexecução, transações de múltiplas requisições ou consultas interativas
- Fornece strong serializability e forte consistência de sessão
- Suporta sucesso/falha de cada operação, retorno de códigos de erro e processamento composto por meio de Chain (subtransações)
Projeto dos testes Jepsen
- Executa testes baseados em propriedades (property-based) e injeção de falhas (fault injection) por meio da biblioteca Jepsen
- Foram realizados experimentos com clusters de 3 a 6 nós em diversos ambientes, como LXC e EC2
- Devido às restrições do modelo de dados, é difícil verificar consistência no formato tradicional de listas e conjuntos, então a validação de consistência de estado e tempo usa a ordem total das operações (total order)
- Detecta erros por meio de abordagens complementares como checagem de consistência baseada em timestamp, validação de modelo e simulação
Validação de modelo e geração de operações
- A correção do comportamento do TigerBeetle é verificada em detalhe com um modelo de máquina de estados single-thread com mais de 1600 linhas
- Inclui raciocínio e rollback para diversas condições de erro, como ids duplicados, timestamps descontínuos, restrições de saldo e chains encadeadas
- Para eficiência da validação, são usadas diversas técnicas, como geração de operações e ids, atualização de estado e composição probabilística de consultas
Injeção de falhas
- Inclui cenários básicos de falha como crash de processo (
SIGKILL), pausa (SIGSTOP), partição de rede e alteração de clock - Também realiza injeções detalhadas de falhas de armazenamento, como upgrade de versão, simulação de corrupção de arquivos e corrupção parcial em apenas algumas réplicas
- Valida a minimização da possibilidade de perda de dados com diversos cenários, incluindo corrupção de disco em zigue-zague (helical)
Principais casos de bugs e melhorias
Problema no tratamento de timeout de requisição (#206)
- No projeto do TigerBeetle, as requisições do cliente nunca entram em timeout; há retry infinito até receber resposta do cluster
- Na prática, clientes como Java podem lançar exceções de timeout em operações assíncronas, e a aplicação acaba precisando definir timeouts externos
- Esse desenho oculta de forma ambígua erros de rede ou erros definitivos, dificultando distinguir falhas claras de erros incertos
- O Jepsen recomendou adicionar formas de retorno por tipo de falha (definitiva/incerta) e opções de retry
Crash da JVM causado por erro no cliente (#2435)
- Wrappers com thread/assíncronos usados para contornar timeout provocaram um problema de segfault na JVM
- O problema ocorreu porque um campo não inicializado corretamente era referenciado no cliente Java; corrigido na versão 0.16.12
Crash do cliente ao expirar a sessão (#2484)
- Encerramento forçado do cliente causado por sessões excessivas
- A partir da versão 0.16.13, isso foi alterado para retorno de erro
Explosão de latência em falha de nó único (#2739)
- Uma fraqueza da replicação baseada em anel fazia com que a latência de resposta de todo o sistema aumentasse drasticamente quando alguns nós falhavam
- Causa: por padrão, o primário envia mensagens passo a passo ao próximo nó; quando alguns nós falham, a ausência de ack causa espera
- A partir da 0.16.30, foram introduzidas replicação em sentido reverso e topologia de anel dinâmica, melhorando fortemente a latência em falhas
Bug na Header API do cliente Java (#2495)
- O uso de um objeto singleton para batch de resposta vazio causava compartilhamento incorreto de header e timestamp
- Não afetava a exatidão dos dados, mas contaminava os resultados da Header API; corrigido na 0.16.14
Omissão de resultados de consulta (#2544)
- Foi reportado um bug na versão 0.16.13 em que resultados de
query_accounts,query_transferse similares eram parcialmente omitidos, limitando a resposta apenas ao prefixo correto
Conclusão
- O TigerBeetle é especializado em ambientes dos setores financeiro e contábil que exigem alto nível de segurança e tolerância a falhas
- A série de testes do Jepsen revelou vários problemas de resiliência, consistência, modelo operacional e desempenho
- Por meio de colaboração ativa, foram obtidas melhorias concretas em resiliência a falhas, tratamento de erros do cliente, replicação e automação de upgrades
- Nas versões mais recentes, o sistema oferece um alto nível de confiabilidade, com resposta mais robusta a falhas, garantias de conexão e resposta, e consistência operacional
(Parte deste conteúdo foi elaborada com referência a várias fontes abertas, incluindo Github, documentação oficial do TigerBeetle e relatórios de teste do Jepsen)
1 comentários
Comentários do Hacker News
O texto Fuzzer Blind Spots (Meet Jepsen!) também foi citado como referência, com indicação de https://tigerbeetle.com/blog/2025-06-06-fuzzer-blind-spots-meet-jepsen/
Compartilha a experiência de sempre confirmar por fim, via relatórios do Jepsen, as alegações sobre confiabilidade e escalabilidade do TigerBeetle; avalia positivamente que este relatório encontrou vários problemas, que eles foram corrigidos rapidamente e que a suíte interna de testes também foi reforçada para evitar a repetição de bugs semelhantes no futuro. Com essa postura, acredita que, em 10 anos, ele possa alcançar no nicho de bancos de dados financeiros especializados o status de padrão implícito do tipo “é só usar Postgres”. Também registra quanto aprendeu com o excelente trabalho do aphyr.
Demonstra alegria ao ver o TigerBeetle validado pelo aphyr e cumprindo o que promete, como um sinal de esperança de que a abordagem correta pode levar ao resultado certo. Pergunta, porém, como consistência e recuperação funcionam na prática entre o TigerBeetle e sistemas externos menos confiáveis, já que em produção muitos dados além de Account ou Transfer costumam ficar em sistemas externos e bancos separados.
Opina que, se a pessoa leu o post sobre blind spots do fuzzer no Jepsen, este relatório do TigerBeetle fica ainda mais interessante. Observa que o caso de segfault via JNI talvez não fosse evitado nem com linguagens memory-safe como Rust, mas avalia que a abordagem Zig/TigerStyle do TigerBeetle oferece uma boa demonstração de segurança de memória.
Fez um pequeno “golf clap” pela criatividade do título da seção "Panic! At the Disk 0".
Expressa forte impressão com este relatório detalhado certificado pelo Jepsen; mesmo antes do lançamento do v1.0, a expectativa já está alta. Também elogia separadamente os fundadores por compartilharem insights de forma ativa na thread.
Considera interessante — e “obviamente óbvio” — que, em testes de sistemas distribuídos, seja essencial para uma verificação precisa que o próprio sistema reporte a ordem/o tempo em que os eventos ocorreram internamente, permitindo comparação exata com o modelo externo.
Depois de revisar o relatório do Jepsen, o blog relacionado e o código de integração com o Antithesis, faz uma pergunta com objetivo de entender o escopo e a eficácia dos testes. Diz que sabia que o TigerBeetle já fazia testes abrangentes com Antithesis, então quer entender como os bugs encontrados pelo Jepsen passaram despercebidos ali, qual é a diferença entre testes com Antithesis e com Jepsen, e como isso difere, em termos concretos, do escopo dos testes internos.
Diz ter interesse no TigerBeetle e estranha que, na documentação de clientes, não haja cliente em C nem em Zig. Pergunta se esses clientes não existem ou ainda estão em desenvolvimento, já que ele próprio é escrito em Zig.
Pergunta se o TigerBeetle já está sendo usado por grandes bancos ou corretoras.