7 pontos por xguru 2024-08-09 | 1 comentários | Compartilhar no WhatsApp
  • rqlite é um banco de dados relacional distribuído, leve e de código aberto, escrito em Go
  • É construído com base no protocolo de consenso Raft e usa SQLite como mecanismo de armazenamento
  • O desenvolvimento da versão 9.0 começou, com o objetivo de reduzir o uso de disco em cerca de 50%
  • Esse objetivo será alcançado por meio de uma reformulação de design em alto nível que elimina a principal causa do consumo de disco no rqlite

O que ocupa a maior parte do uso atual de disco?

  • Log do Raft:
    • Um registro das alterações no sistema
    • Esse log é o núcleo do sistema de consenso Raft
  • Banco de dados SQLite ativo:
    • O banco de dados em produção que o rqlite usa para fornecer leituras e escritas
    • Quando uma instrução SQLite é confirmada com sucesso no log do Raft, ela é aplicada ao banco de dados SQLite ativo
  • Snapshot do banco de dados SQLite ativo:
    • Para evitar que o log do Raft cresça sem limite, o subsistema Raft dentro do rqlite cria e armazena periodicamente uma cópia pontual do banco de dados SQLite ativo
    • Essa cópia é chamada de snapshot
    • Quando um snapshot é criado, o rqlite pode truncar o log do Raft
    • Essa cópia em snapshot é usada pelo rqlite para restaurar um nó quando ele é reiniciado, ou é enviada a outro nó quando esse nó precisa “alcançar” o estado de um cluster rqlite existente
    • A criação de snapshots e o truncamento de logs são conceitos centrais em sistemas baseados em Raft

Design em alto nível para o rqlite 9.0

  • A principal estratégia para reduzir o uso de disco é eliminar a necessidade de armazenar uma cópia em snapshot do banco de dados SQLite ativo dentro do sistema Raft
  • O log do Raft é truncado periodicamente por causa da criação de snapshots e para de crescer após certo ponto, mas o banco de dados SQLite ativo continua aumentando à medida que mais dados são gravados
  • E, como a cópia em snapshot do banco de dados SQLite tem praticamente o mesmo tamanho do banco de dados SQLite ativo, ela também cresce
  • Portanto, se essa cópia em snapshot puder ser eliminada, o rqlite usará 50% menos disco
  • No entanto, um nó rqlite precisa de uma cópia em snapshot em determinados momentos. Isso não pode ser evitado.
  • Então, como pular essa cópia e ainda atender à necessidade de criação e restauração de snapshots?
  • Para entender como isso pode ser evitado sem armazenar uma cópia extra durante o processo de snapshot, é importante saber que o rqlite executa o banco de dados SQLite subjacente no modo Write-Ahead Log (WAL)
  • No design proposto para a versão 9.0, o arquivo do banco de dados SQLite ativo (excluindo o arquivo WAL relacionado) e a cópia em snapshot no sistema Raft são logicamente idênticos
  • Aproveitando esse fato, é possível eliminar a necessidade de armazenar uma cópia em snapshot separada no sistema Raft

Nova abordagem para criação de snapshots

  • Criação de snapshot e checkpoint do WAL:
    • No momento da criação do snapshot, o rqlite faz checkpoint do Write-Ahead Log (WAL) do banco de dados SQLite ativo
    • Todas as gravações posteriores passam a ir para um novo arquivo WAL, de modo que o arquivo SQLite principal permanece inalterado a partir do ponto em que o snapshot foi criado
    • Como resultado, até que o próximo snapshot ocorra, o arquivo SQLite principal representa o estado pontual exigido pelo armazenamento de snapshots do Raft
    • Essa abordagem permite usar o arquivo SQLite combinado com o arquivo WAL para operações normais de leitura e escrita, enquanto o arquivo SQLite principal inalterado atua como o conjunto de dados do armazenamento de snapshots do Raft
    • Não é mais necessária nenhuma cópia adicional!
  • Gravação de referência no armazenamento de snapshots:
    • Em vez de copiar o arquivo SQLite inteiro, o rqlite grava uma referência, como um checksum, no armazenamento de snapshots
    • Essa referência pode ser usada para verificar, sempre que os dados do snapshot forem necessários, se o arquivo SQLite principal corresponde ao que é referenciado pelo armazenamento de snapshots
      • (Essa verificação protege contra bugs, erros operacionais ou corrupção de disco, mas não é estritamente necessária)
  • Restauração a partir do snapshot:
    • Como mencionado anteriormente, todas as gravações após o processo de snapshot vão para o arquivo WAL, então o arquivo SQLite principal fica pronto para ser usado no processo de restauração a partir do snapshot, como em uma reinicialização do nó ou ao enviar o snapshot para outro nó
    • Ou seja, o arquivo SQLite principal (ignorando o arquivo WAL relacionado) permanece logicamente idêntico ao que teria sido gravado no armazenamento de snapshots do Raft se o rqlite realmente tivesse criado uma cópia duplicada
  • Esse novo design é chamado de “snapshot por referência”

Melhorias extras

  • O snapshot por referência também trará algumas outras melhorias importantes
  • Criação de snapshots mais rápida: como grava apenas o mínimo de dados no armazenamento de snapshots do Raft, o processo de snapshot será muito mais rápido
    • Ele será composto pelo tempo de checkpoint do WAL do SQLite (normalmente muito curto) e pelo tempo de cálculo do checksum
    • Não será mais necessário copiar grandes volumes de dados SQLite para o armazenamento de snapshots toda vez que um snapshot for criado
    • Fica claro o benefício de snapshots mais rápidos ao considerar que as gravações no rqlite são bloqueadas durante o processo de snapshot
  • Reinicialização mais rápida: mesmo nós com vários gigabytes de dados SQLite reiniciarão muito mais rapidamente
    • Atualmente, ao reiniciar, o rqlite precisa restaurar o arquivo ativo do banco de dados SQLite a partir de uma cópia armazenada no armazenamento de snapshots do Raft
    • Porém, nesse novo design, na inicialização o arquivo ativo do banco de dados SQLite já estará no local correto
    • No máximo, o rqlite só precisará comparar o checksum do armazenamento de snapshots com o checksum do banco de dados SQLite ativo
    • Sistemas com vários GB devem reiniciar em poucos segundos

Próximos passos

  • A transição para o rqlite 9.0 será um passo importante na otimização da eficiência do rqlite
  • Ao implementar snapshots por referência, espera-se reduzir significativamente o uso de disco, acelerar a criação de snapshots e melhorar o tempo de reinicialização dos nós
  • Há muitos detalhes que precisam ser tratados corretamente, como o gerenciamento do SQLite WAL, upgrades suaves a partir de versões anteriores e a escolha do checksum
  • Portanto, acompanhe as próximas atualizações à medida que o trabalho rumo a esse grande lançamento avançar