1 puntos por GN⁺ 2025-04-02 | Aún no hay comentarios. | Compartir por WhatsApp
  • Graft es un motor de almacenamiento transaccional open source que busca combinar la simplicidad de la replicación física con la eficiencia de la replicación lógica, en lugar de enviar el registro completo de cambios a todos los clientes
  • Maneja Volumes compuestos por Pages de tamaño fijo en unidades de Snapshots, y el servidor entrega un graft, un bitset comprimido de los índices de páginas modificadas, no los datos reales
  • El cliente revisa el graft y trae solo las Pages necesarias; puede elegir prefetching basado en Leap, prefetching específico del dominio o una carga anticipada que trae todos los cambios
  • Usa almacenamiento de objetos y servidores edge para apuntar a la replicación parcial incluso en entornos restringidos como navegadores, apps móviles, funciones serverless y entornos embebidos
  • El modelo de consistencia es Serializable Snapshot Isolation; rechaza commits basados en Snapshots antiguas y el cliente los maneja con reset/replay, merge o fork de Volume

El problema de replicación que Graft intenta resolver

  • La replicación parcial parece sencilla si solo se sincronizan los datos necesarios, pero en el diseño real cada enfoque de replicación tiene costos claros
    • La replicación lógica rastrea con precisión todos los cambios, pero vuelve compleja la consistencia fuerte
    • La replicación física evita esa complejidad, pero obliga a sincronizar incluso cambios que después se descartarán
  • Graft es un motor de almacenamiento transaccional open source creado con el objetivo de ofrecer sincronización diferida, replicación parcial, consistencia fuerte, escalabilidad horizontal y durabilidad mediante almacenamiento de objetos
  • El punto de partida fue la experiencia con SQLSync
    • SQLSync es un stack de base de datos optimizado para frontend construido sobre SQLite, que usa ideas de Git y de sistemas distribuidos en su motor de sincronización
    • SQLSync replica el registro completo de cambios a todos los clientes; eso funciona bien en servidores, pero no encaja con entornos edge ni navegadores
  • El objetivo de Graft es que los clientes sincronicen al ritmo que quieran, traigan solo lo necesario y repliquen datos arbitrarios con consistencia fuerte incluso en el edge y en dispositivos offline

Un diseño entre la replicación completa y los diff conscientes del esquema

  • Las soluciones existentes se dividen en dos grandes grupos
    • Replicación completa: sincroniza todo el dataset en cada cliente, por lo que no es práctica en entornos restringidos como funciones serverless o apps web
    • Diff conscientes del esquema: rastrean cambios lógicos a nivel de fila o campo, como CDC o CRDT, pero requieren una integración profunda con la aplicación y son difíciles de generalizar a datos arbitrarios
  • Graft es independiente del esquema, como la replicación completa
    • Replica páginas con bytes, sin saber ni preocuparse por el tipo de datos almacenados
  • Al mismo tiempo, como la replicación lógica, entrega al cliente una descripción comprimida de qué cambió desde la última sincronización
  • La abstracción central es el Volume
    • Un Volume es una colección dispersa y ordenada de Pages de tamaño fijo
    • El cliente lee y escribe un Volume desde una Snapshot específica mediante una API transaccional
    • Internamente, Graft almacena y replica solo lo necesario, y usa almacenamiento de objetos como backend durable y escalable

Sincronización diferida: ponerse al día cuando el cliente quiera

  • Graft está diseñado asumiendo clientes edge que se activan de vez en cuando, redes inestables y tiempos de ejecución cortos
  • No depende de replicación continua; el cliente decide directamente cuándo sincronizar
  • La sincronización empieza con la pregunta: “qué cambió desde la última Snapshot”
  • El servidor no envía los datos reales; responde con un graft, un bitset comprimido de los índices de páginas modificadas
    • graft funciona como una guía para adjuntar los nuevos cambios a la Snapshot existente
    • El cliente puede saber qué páginas puede reutilizar y qué páginas deberá traer cuando las necesite
  • Como graft no son datos sino metadatos de cambios, el control sobre qué traer y cuándo permanece en el cliente

Replicación parcial y prefetching

  • En pestañas de navegador, apps móviles y funciones serverless, es difícil descargar todo el dataset para procesar algunas consultas
  • Después de recibir el graft, el cliente determina qué páginas siguen siendo válidas y cuáles debe traer
  • Como trae selectivamente solo las páginas necesarias, puede replicar únicamente los datos que realmente va a usar
  • Graft soporta varios métodos de prefetching para reducir la latencia de acceso a páginas
    • Prefetching de propósito general: un prefetcher integrado basado en el algoritmo Leap identifica patrones de acceso y predice futuros accesos a páginas
    • Prefetching específico del dominio: la aplicación puede usar su conocimiento sobre datos consultados con frecuencia, como perfiles de usuario, para traer páginas relacionadas con anticipación
    • Carga anticipada: si es necesario, puede traer todos los cambios y, en la práctica, volver a una replicación completa; esto es especialmente útil para cargas de trabajo de Graft del lado del servidor
  • Como las páginas se alojan directamente en almacenamiento de objetos, sirven como base de replicación durable y escalable

Despliegue en edge y clientes embebidos

  • La replicación edge de Graft no solo busca decidir qué datos sincronizar, sino también colocar los datos donde se necesitan
  • Las páginas se sirven desde almacenamiento de objetos mediante una flota global de servidores edge
    • Las hot pages accedidas con frecuencia pueden cachearse cerca del cliente
    • El objetivo es baja latencia y alta capacidad de respuesta, sin importar dónde estén los usuarios en el mundo
  • El cliente de Graft está diseñado para ser liviano y embebible
    • Tiene pocas dependencias y un runtime pequeño
    • Puede integrarse en entornos como navegadores, dispositivos, apps móviles y funciones serverless
  • Como el caché en edge introduce problemas de consistencia y manejo de conflictos, Graft también ofrece un modelo de consistencia fuerte

Modelo de consistencia y manejo de conflictos

  • Graft usa Serializable Snapshot Isolation como modelo de consistencia
  • El cliente obtiene una vista aislada y consistente de los datos en una Snapshot específica, y las lecturas pueden ejecutarse simultáneamente sin interferir entre sí
  • Las escrituras se serializan estrictamente, lo que crea un orden globalmente consistente para todas las transacciones
  • Por su naturaleza offline-first y de replicación diferida, el cliente puede intentar hacer commit basándose en una Snapshot antigua
    • Aceptar esos commits sin condiciones rompería la strict serializability
    • Graft rechaza esos commits de forma segura y permite que el cliente elija cómo manejarlos
  • Las opciones habituales del cliente son tres
    • Reset and replay: trae la Snapshot más reciente, vuelve a aplicar la transacción local y reintenta
      • Los datos globales mantienen un estado strict serializable
      • Localmente se experimenta Optimistic Snapshot Isolation: las lecturas ven una Snapshot internamente consistente, pero esa Snapshot puede descartarse si se rechaza el commit
    • Merge: combina el estado local con la Snapshot más reciente del servidor
      • En este caso, el modelo de consistencia global puede degradarse a snapshot isolation
    • Volume fork: crea de forma permanente un nuevo Volume separado
      • Mantiene la serializability global

Aplicaciones que se pueden crear

  • Apps offline-first: en apps que funcionan parcialmente offline, como notas, gestión de tareas o apps CRUD, Graft puede encargarse de la sincronización
    • Combinado con manejadores de conflictos, también permite funciones multiplayer sobre datos arbitrarios
  • Datos multiplataforma: permite compartir datos entre plataformas móviles, dispositivos y la web, y reduce la dependencia de un proveedor
  • Réplicas de lectura sin estado: permite levantar una réplica de base de datos sin estado local, traer la metadata de la Snapshot más reciente y ejecutar consultas de inmediato
    • No hace falta descargar todos los datos ni reproducir logs
  • Replicación de datos arbitrarios: Graft se enfoca en replicar páginas, por lo que no interviene en el formato de datos dentro de cada página

Extensión SQLite libgraft

  • Actualmente, la forma más fácil de usar Graft es libgraft, una extensión nativa de SQLite
  • libgraft puede usarse donde funcione SQLite, y replica solo la parte de la base de datos que el cliente realmente utiliza
  • Implementa SQLite VFS para interceptar lecturas y escrituras de la base de datos
  • Ofrece semánticas de transacción y concurrencia similares a las que SQLite proporciona en WAL mode
  • Sus funciones incluyen
    • Replicación asíncrona con almacenamiento de objetos
    • Replicación parcial diferida en edge y dispositivos
    • Serializable Snapshot Isolation
    • Restauración a un punto en el tiempo
  • La documentación está disponible en la documentación de SQLite en GitHub

Participación y planes de servicio gestionado

  • Graft se desarrolla públicamente en GitHub
  • Acepta issues, discusiones y Pull Requests, y ofrece una guía de contribución
  • Discord y correo electrónico están disponibles como canales de conversación
  • También está previsto lanzar Graft Managed Service, y se ofrece un enlace para sumarse a la lista de espera

Roadmap

  • Graft ha pasado por un año de investigación, varias iteraciones y un gran cambio de dirección, pero aún queda mucho trabajo
  • Los puntos planificados son
    • Soporte para WebAssembly: habilitar el uso de Graft en el navegador, con el objetivo de soportar el build oficial Wasm de SQLite, wa-sqlite y sql.js
    • Integración de Graft y SQLSync: después del soporte Wasm, se planea separar las capas de mutation, rebase y query subscription de SQLSync y montarlas sobre una base de datos replicada con Graft
    • Ampliación de bibliotecas cliente: se buscan wrappers nativos de cliente Graft para Python, JavaScript, Go y Java
    • Escrituras de baja latencia: actualmente, las operaciones push se bloquean hasta que el commit queda completamente confirmado en almacenamiento de objetos
      • Experimentos con S3 express zone
      • Un enfoque con un grupo de consenso durable y de baja latencia frente al almacenamiento de objetos
    • Garbage collection, checkpointing y compaction: necesarios para maximizar el rendimiento de consultas, minimizar espacio desperdiciado y permitir borrado permanente
    • Autenticación y autorización: un trabajo amplio que va desde cuentas de servicio gestionado hasta permisos granulares de lectura/escritura por Volume
    • Volume forking: el servicio puede realizar un fork zero-copy copiando referencias de Segments a un nuevo Volume, pero un fork local actualmente debe copiar todas las páginas
    • Manejo de conflictos: se planea ofrecer estrategias integradas de resolución de conflictos y puntos de extensión; la estrategia inicial será fusionar automáticamente transacciones que no se superpongan

Comparación con soluciones de replicación de SQLite

  • La información comparativa se recopiló de documentación y posts de blog, con la advertencia de que podría no ser totalmente precisa
  • mvSQLite

    • mvSQLite implementa una capa VFS personalizada que almacena páginas de SQLite directamente en FoundationDB
    • Graft y mvSQLite se parecen en que el versionado a nivel de página permite fetch diferido y vistas parciales de la base de datos
    • La diferencia está en dónde se almacena y cómo se rastrean los cambios de páginas
      • mvSQLite depende de FoundationDB y todos los nodos deben acceder directamente al clúster
      • El changeset basado en Splinter de Graft es autocontenido, por lo que es fácil de desplegar y no hace falta consultar directamente FoundationDB para saber qué versiones de páginas cambiaron
  • Litestream

    • Litestream es una solución de backup por streaming que replica continuamente frames WAL de SQLite en almacenamiento de objetos
    • Graft se integra directamente en el proceso de commit de SQLite mediante un VFS personalizado, lo que permite replicación parcial diferida y escrituras distribuidas
    • Ambos replican páginas en almacenamiento de objetos y soportan restauración a un punto en el tiempo
  • cr-sqlite

    • cr-sqlite es una extensión de SQLite que convierte tablas en CRDT para permitir replicación lógica a nivel de fila
    • Ofrece resolución automática de conflictos, pero requiere conocimiento del esquema e integración a nivel de aplicación
    • Graft es independiente del esquema y compatible con extensiones arbitrarias de SQLite y estructuras de datos personalizadas, pero para mantener la serializability global la aplicación debe manejar explícitamente la resolución de conflictos
  • Cloudflare Durable Objects with SQLite Storage

    • Combinar Durable Objects con SQLite permite ubicar una base de datos de alta durabilidad y consistencia fuerte, envuelta en lógica de negocio, en la red edge de Cloudflare
    • Internamente, se parece a Litestream en que replica el WAL de SQLite a almacenamiento de objetos y hace checkpoints periódicos
    • Graft expone la replicación como una función de primera clase y apunta a una replicación eficiente con el edge
  • Cloudflare D1

    • Cloudflare D1 es una base de datos SQLite gestionada accesible mediante una API HTTP
    • Graft es un modelo distribuido que embebe los datos en la aplicación cliente y los replica directamente al edge
  • Turso & libSQL

    • Turso ofrece bases de datos SQLite gestionadas y réplicas embebidas mediante libSQL
    • Graft se diferencia por la replicación parcial y el soporte para estructuras de datos arbitrarias e independientes del esquema
    • El servicio backend de Graft opera a nivel de página y deja todo el ciclo de vida transaccional en manos del cliente
  • rqlite & dqlite

    • rqlite y dqlite distribuyen SQLite en varios servidores mediante consenso basado en Raft y un protocolo de red
    • Se enfocan en sincronizar un conjunto de nodos con estado que mantienen conexión entre sí
    • Graft es un sistema sin estado construido sobre almacenamiento de objetos y diseñado para intercambiar datos con el edge
  • Verneuil

    • Verneuil replica de forma asíncrona Snapshots de SQLite a réplicas de lectura mediante almacenamiento de objetos y prioriza la confiabilidad
    • Evita explícitamente mecanismos para minimizar el retraso de replicación o maximizar la frescura
    • Graft se comporta más como una base de datos distribuida con múltiples escritores y enfatiza la replicación parcial selectiva en tiempo real

Aún no hay comentarios.

Aún no hay comentarios.