1 pontos por GN⁺ 2025-04-02 | Ainda não há comentários. | Compartilhar no WhatsApp
  • Graft é um motor de armazenamento transacional open source que busca combinar a simplicidade da replicação física com a eficiência da replicação lógica, em vez de enviar o log completo de mudanças para todos os clientes
  • Ele trata Volumes compostos por Pages de tamanho fixo em unidades de Snapshot, e o servidor entrega não os dados em si, mas um bitmap comprimido dos índices de páginas alteradas, chamado graft
  • O cliente consulta o graft e busca apenas as páginas necessárias, podendo escolher entre prefetch baseado em Leap, prefetch específico de domínio ou busca antecipada de todas as mudanças
  • Usando armazenamento de objetos e servidores de borda, ele busca replicação parcial mesmo em ambientes restritos como navegador, apps móveis, funções serverless e sistemas embarcados
  • O modelo de consistência é Serializable Snapshot Isolation; commits baseados em Snapshots antigos são rejeitados, e o cliente lida com isso usando reset/replay, merge ou fork de Volume

O problema de replicação que o Graft quer resolver

  • A replicação parcial parece simples quando se pensa em sincronizar apenas os dados necessários, mas na prática cada abordagem de replicação tem custos bem claros
    • A replicação lógica rastreia todas as mudanças com precisão, mas torna mais complexa a obtenção de consistência forte
    • A replicação física evita essa complexidade, mas exige sincronizar até mudanças que depois serão descartadas
  • Graft é um motor de armazenamento transacional open source criado com foco em sincronização sob demanda, replicação parcial, consistência forte, escalabilidade horizontal e durabilidade em armazenamento de objetos
  • O ponto de partida veio da experiência com o SQLSync
    • SQLSync é uma stack de banco de dados otimizada para frontend construída sobre SQLite, que usa ideias de Git e sistemas distribuídos no mecanismo de sincronização
    • Como o SQLSync replica o log completo de mudanças para todos os clientes, ele funciona no servidor, mas não se encaixa bem em ambientes de borda e navegadores
  • O objetivo do Graft é permitir que os clientes sincronizem no próprio ritmo, busquem apenas o necessário e repliquem dados arbitrários com consistência forte, inclusive em edge e dispositivos offline

Um desenho entre replicação completa e diff com conhecimento de esquema

  • As soluções existentes se dividem em duas grandes linhas
    • Replicação completa: sincroniza o dataset inteiro com cada cliente, o que não é prático em ambientes restritos como funções serverless ou apps web
    • Diff com conhecimento de esquema: rastreia mudanças lógicas no nível de linha ou campo, como CDC ou CRDT, mas exige integração profunda com a aplicação e é difícil de generalizar para dados arbitrários
  • O Graft, assim como a replicação completa, independe de esquema
    • Ele não precisa saber nem se importar com o tipo de dado armazenado; replica páginas contendo bytes
  • Ao mesmo tempo, como a replicação lógica, ele entrega ao cliente uma descrição comprimida do que mudou desde a última sincronização
  • A abstração central é o Volume
    • Um Volume é uma coleção esparsa e ordenada de Pages de tamanho fixo
    • O cliente lê e escreve no Volume a partir de um Snapshot específico usando uma API transacional
    • Internamente, o Graft armazena e replica apenas o necessário, usando armazenamento de objetos como backend durável e escalável

Sincronização sob demanda: alcançar o estado atual quando o cliente quiser

  • O Graft foi projetado assumindo clientes de borda que despertam ocasionalmente, operam em redes instáveis e têm pouco tempo de execução
  • Em vez de depender de replicação contínua, o cliente escolhe quando sincronizar
  • A sincronização começa com a pergunta: “o que mudou desde o último Snapshot?”
  • O servidor não envia os dados reais, mas sim o graft, um bitmap comprimido dos índices das páginas alteradas
    • O graft funciona como um guia para anexar novas mudanças a um Snapshot existente
    • O cliente consegue saber quais páginas pode reutilizar e quais deverá buscar sob demanda
  • Como o graft é metadado de mudança, não dado em si, o controle sobre o que buscar e quando buscar permanece com o cliente

Replicação parcial e prefetch

  • Em abas de navegador, apps móveis e funções serverless, é difícil baixar o dataset inteiro só para atender algumas consultas
  • Depois de receber o graft, o cliente determina quais páginas ainda são válidas e quais precisam ser buscadas
  • Como apenas as páginas necessárias são buscadas seletivamente, dá para replicar somente os dados que realmente serão usados
  • O Graft oferece vários modos de prefetch para reduzir a latência de acesso às páginas
    • Prefetch de uso geral: um prefetcher embutido baseado no algoritmo Leap identifica padrões de acesso e prevê acessos futuros a páginas
    • Prefetch específico de domínio: a aplicação pode usar conhecimento sobre dados consultados com frequência, como perfis de usuários, para antecipar páginas relacionadas
    • Busca antecipada: se necessário, é possível buscar todas as mudanças e voltar, na prática, à replicação completa, algo especialmente útil para cargas de trabalho de Graft no lado do servidor
  • Como as páginas ficam hospedadas diretamente no armazenamento de objetos, isso serve de base de replicação com durabilidade e escalabilidade

Implantação em edge e clientes embarcados

  • A replicação em edge do Graft não busca apenas decidir quais dados sincronizar, mas também colocar os dados onde eles são necessários
  • As páginas são servidas a partir do armazenamento de objetos por meio de uma frota global de servidores de borda
    • Hot pages acessadas com frequência podem ser armazenadas em cache perto do cliente
    • O objetivo é manter baixa latência e alta responsividade independentemente da localização dos usuários no mundo
  • O cliente Graft foi projetado para ser leve e embarcável
    • Tem poucas dependências e runtime pequeno
    • Pode ser integrado a ambientes como navegador, dispositivos, apps móveis e funções serverless
  • Como o cache de edge cria problemas de consistência e tratamento de conflitos, o Graft também oferece um modelo de consistência forte

Modelo de consistência e tratamento de conflitos

  • O Graft usa Serializable Snapshot Isolation como modelo de consistência
  • O cliente obtém uma visão isolada e consistente dos dados em um Snapshot específico, e leituras podem ocorrer em paralelo sem interferência mútua
  • Escritas são serializadas rigidamente, criando uma ordem globalmente consistente para todas as transações
  • Por causa da abordagem offline-first e da replicação adiada, um cliente pode tentar fazer commit com base em um Snapshot antigo
    • Se esse commit fosse sempre aceito, a strict serializability seria quebrada
    • O Graft rejeita esse commit com segurança e deixa o cliente escolher como lidar com a situação
  • As três opções mais comuns do cliente são:
    • Reset and replay: buscar o Snapshot mais recente, reaplicar as transações locais e tentar de novo
      • O estado global dos dados permanece strict serializable
      • Localmente, há uma experiência de Optimistic Snapshot Isolation: as leituras veem um Snapshot internamente consistente, mas ele pode ser descartado se o commit for rejeitado
    • Merge: mesclar o estado local com o Snapshot mais recente do servidor
      • Nesse caso, o modelo global de consistência pode cair para snapshot isolation
    • Volume fork: separar permanentemente em um novo Volume
      • A serializabilidade global é preservada

Aplicações que podem ser construídas

  • Apps offline-first: em apps que funcionam parcialmente offline, como notas, gerenciamento de tarefas e apps CRUD, o Graft pode cuidar da sincronização
    • Em conjunto com um tratador de conflitos, também pode habilitar recursos multiplayer sobre dados arbitrários
  • Dados multiplataforma: permite compartilhar dados entre plataformas móveis, dispositivos e web, reduzindo dependência de fornecedor
  • Réplicas de leitura sem estado: é possível subir uma réplica do banco sem estado local, buscar os metadados do Snapshot mais recente e executar consultas imediatamente
    • Não é necessário baixar todos os dados nem reproduzir logs
  • Replicação de dados arbitrários: como o Graft foca na replicação de páginas, ele não interfere no formato interno dos dados

Extensão SQLite libgraft

  • Hoje, a forma mais simples de usar o Graft é com a extensão nativa de SQLite libgraft
  • O libgraft pode ser usado onde quer que o SQLite rode e replica apenas a parte do banco que o cliente realmente utiliza
  • Ele implementa a VFS do SQLite para interceptar leituras e escritas no banco
  • Fornece a mesma semântica de transação e concorrência que o SQLite oferece em WAL mode
  • Os recursos oferecidos incluem:
    • Replicação assíncrona com armazenamento de objetos
    • Replicação parcial adiada em edge e dispositivos
    • Serializable Snapshot Isolation
    • Restauração em um ponto no tempo
  • A documentação pode ser consultada na documentação de SQLite no GitHub

Participação e planos de serviço gerenciado

  • O Graft é desenvolvido abertamente no GitHub
  • Issues, discussões e Pull Requests são bem-vindos, e há um guia de contribuição
  • Também há canais de contato via Discord e e-mail
  • Existe ainda um plano para lançar o Graft Managed Service, com link para lista de espera

Roadmap

  • O Graft passou por um ano de pesquisa, várias iterações e uma grande mudança de direção, mas ainda há muito trabalho pela frente
  • Entre os itens planejados estão:
    • Suporte a WebAssembly: permitir o uso do Graft no navegador, com meta de suportar o build oficial Wasm do SQLite, wa-sqlite e sql.js
    • Integração entre Graft e SQLSync: após o suporte a Wasm, a ideia é separar as camadas de mutation, rebase e query subscription do SQLSync e colocá-las sobre um banco replicado com Graft
    • Expansão das bibliotecas cliente: interesse em wrappers nativos de cliente Graft para Python, JavaScript, Go e Java
    • Escritas de baixa latência: hoje a operação de push fica bloqueada até o commit completo no armazenamento de objetos
      • Experimentos com S3 express zone
      • Uso de um grupo de consenso durável e de baixa latência na frente do armazenamento de objetos
    • Coleta de lixo, checkpointing e compactação: necessários para maximizar o desempenho de consulta, minimizar espaço desperdiçado e permitir exclusão permanente
    • Autenticação e autorização: um trabalho amplo, do gerenciamento de contas do serviço até permissões granulares de leitura e escrita por Volume
    • Volume forking: o serviço consegue fazer fork zero-copy copiando referências de Segment para um novo Volume, mas o fork local ainda precisa copiar todas as páginas
    • Tratamento de conflitos: há planos para estratégias embutidas de resolução e pontos de extensão; a estratégia inicial será mesclar automaticamente transações que não se sobrepõem

Comparação com soluções de replicação para SQLite

  • As comparações foram reunidas a partir de documentação e posts de blog, com a ressalva de que podem não estar 100% corretas
  • mvSQLite

    • mvSQLite implementa uma camada VFS customizada que armazena páginas do SQLite diretamente no FoundationDB
    • Graft e mvSQLite se parecem por permitir fetch sob demanda e visões parciais do banco via versionamento em nível de página
    • A diferença está em onde os dados ficam e como as mudanças de página são rastreadas
      • O mvSQLite depende de FoundationDB, e todos os nós precisam acessar o cluster diretamente
      • O changeset do Graft baseado em Splinter é autocontido, facilita a implantação e dispensa consultas diretas ao FoundationDB para descobrir versões alteradas de páginas
  • Litestream

    • Litestream é uma solução de backup em streaming que replica continuamente frames do WAL do SQLite para armazenamento de objetos
    • O Graft se integra diretamente ao processo de commit do SQLite por meio de uma VFS customizada, permitindo replicação parcial adiada e escritas distribuídas
    • Ambos replicam páginas para armazenamento de objetos e suportam restauração em um ponto no tempo
  • cr-sqlite

    • cr-sqlite é uma extensão de SQLite que transforma tabelas em CRDTs para permitir replicação lógica em nível de linha
    • Ele oferece resolução automática de conflitos, mas exige conhecimento de esquema e integração no nível da aplicação
    • O Graft é independente de esquema e compatível com extensões arbitrárias de SQLite e estruturas de dados customizadas, mas exige que a aplicação trate explicitamente a resolução de conflitos para preservar a serializabilidade global
  • Cloudflare Durable Objects with SQLite Storage

    • A combinação de Durable Objects com SQLite permite manter um banco de dados com consistência forte e alta durabilidade na rede de edge da Cloudflare, encapsulado por lógica de negócio
    • Internamente, isso se parece com o Litestream ao replicar o WAL do SQLite para armazenamento de objetos e fazer checkpoints periódicos
    • O Graft expõe a replicação como recurso de primeira classe e busca eficiência na replicação com edge
  • Cloudflare D1

    • Cloudflare D1 é um banco SQLite gerenciado acessado por API HTTP
    • O Graft segue um modelo distribuído em que os dados ficam embutidos na aplicação cliente e são replicados diretamente até a edge
  • Turso & libSQL

    • Turso oferece banco SQLite gerenciado e réplicas embarcadas por meio do libSQL
    • O Graft se diferencia por oferecer replicação parcial e suporte a estruturas de dados arbitrárias sem dependência de esquema
    • O serviço backend do Graft opera no nível de página e deixa todo o ciclo de vida da transação nas mãos do cliente
  • rqlite & dqlite

    • rqlite e dqlite distribuem SQLite por meio de consenso baseado em Raft e protocolo de rede
    • Eles focam em sincronizar conjuntos de nós com estado que mantêm conexões entre si
    • O Graft é um sistema stateless construído sobre armazenamento de objetos, projetado para trocar dados com a edge
  • Verneuil

    • Verneuil replica assincronamente Snapshots do SQLite para réplicas de leitura por meio de armazenamento de objetos, priorizando confiabilidade
    • Ele evita explicitamente mecanismos para minimizar atraso de replicação ou maximizar frescor dos dados
    • O Graft opera mais como um banco distribuído com múltiplos escritores e enfatiza replicação parcial seletiva em tempo quase real

Ainda não há comentários.

Ainda não há comentários.