Litestream VFS
(fly.io)- Litestream VFS est une extension sous forme de plugin qui permet de lire et d’interroger directement une base de données SQLite depuis un stockage objet (comme S3)
- Permet d’effectuer des requêtes immédiates sur des fichiers de sauvegarde distants et une restauration à un instant donné (Point-in-Time Recovery, PITR) sans télécharger toute la base de données
- Utilise en interne le format LTX pour gérer efficacement les ensembles de pages modifiées, et améliore la vitesse de restauration grâce à une compaction qui ignore les pages dupliquées
- Exploite l’interface VFS de SQLite pour n’intercepter que les opérations de lecture, tandis que l’écriture reste prise en charge par le processus Litestream existant
- Grâce à des sauvegardes à la seconde et à des mises à jour d’index, fournit une réplique quasi temps réel, adaptée à l’exécution rapide de requêtes dans le cloud
Présentation de Litestream VFS
- Litestream VFS permet à SQLite d’utiliser directement une URL de stockage objet comme source de données
- S’active dans le shell SQLite avec les commandes
.load litestream.soet.open file:///my.db?vfs=litestream - Il devient ensuite possible d’exécuter des requêtes à partir de fichiers de sauvegarde stockés sur S3
- S’active dans le shell SQLite avec les commandes
- Il est possible d’interroger directement une sauvegarde distante sans télécharger toute la base de données
- Dans l’exemple, la requête
SELECT * FROM sandwich_ratingspermet de consulter immédiatement une partie des données stockées sur S3
- Dans l’exemple, la requête
Fonction de restauration à un instant donné (PITR)
- La commande
PRAGMA litestream_time = '5 minutes ago';permet de consulter l’état des données à un instant précis- Il est possible de spécifier une heure relative (
5 minutes ago) ou absolue (2000-01-01T00:00:00Z)
- Il est possible de spécifier une heure relative (
- Cela permet d’effectuer une restauration instantanée à un instant donné (Point-in-Time Recovery) au niveau SQL
- Dans l’exemple, après l’exécution d’un
UPDATEerroné, un retour à l’état d’il y a 5 minutes permet de vérifier les données correctes
- Dans l’exemple, après l’exécution d’un
Format LTX et compression des données
- Litestream v0.5 intègre le format LTX (Litestream Transaction eXchange)
- Les versions précédentes transféraient des pages SQLite entières, tandis que LTX ne transfère qu’un ensemble ordonné de pages
- L’élément clé de LTX est la fonction « compaction », qui sélectionne uniquement la version la plus récente de chaque page lors de la restauration
- Exemple : dans
1 2 3 5 3 5 4 5 5, seules les occurrences les plus à droite de 5, 4, 3, 2 et 1 sont utilisées
- Exemple : dans
- LTX peut être compressé non seulement pour une base complète, mais aussi entre des ensembles de fichiers LTX, ce qui rend possible la restauration PITR
- Le trailer des fichiers LTX contient un index des offsets de chaque page, ce qui permet de
- lire uniquement les pages nécessaires via des requêtes S3 Range sans télécharger le fichier entier
Méthode d’implémentation du VFS
- Litestream VFS est implémenté à l’aide de l’interface VFS (Virtual File System) de SQLite
- Le VFS est une structure de plugin qui abstrait la couche d’accès à l’OS de SQLite
- Litestream VFS ne traite que les opérations de lecture (Read), tandis que les opérations d’écriture (Write) sont prises en charge par le processus Litestream existant
- Lorsque SQLite lit une page, le VFS effectue un mappage basé sur l’index des pages au lieu d’utiliser directement l’offset en octets demandé
- Il retrouve dans l’index le nom du fichier, l’offset réel et la taille de page, puis télécharge uniquement le bloc concerné via l’en-tête Range de l’API S3
- Un cache LRU conserve en mémoire les « hot pages » fréquemment consultées afin de minimiser les appels à S3
Réplication en temps réel et performances
- Litestream effectue une sauvegarde de niveau L0 une fois par seconde
- Le VFS interroge périodiquement le chemin S3 et met à jour progressivement l’index
- Il en résulte une réplique quasi temps réel (near-realtime replica)
- L’utilisation est immédiate, sans avoir à streamer l’intégralité de la base de données
- Cette architecture permet d’obtenir un démarrage rapide et des temps de restauration courts
Usages et intérêt
- Litestream conserve en sauvegarde tous les états de la base de données avec une résolution à la seconde
- En cas d’erreur de
DELETEou deUPDATE, il est possible de restaurer immédiatement l’instant souhaité
- En cas d’erreur de
- L’interrogation directe depuis un stockage objet permet un fonctionnement rapide même dans des environnements de serveurs éphémères
- En s’appuyant sur les fonctions natives de SQLite sans mécanismes complexes, il fournit un système de sauvegarde et de restauration simple mais puissant
- Il est aussi utilisé dans l’API interne de Fly.io et peut être exploité de manière stable en production
1 commentaires
Commentaires Hacker News
Ça me fait toujours vraiment plaisir de voir que le code que j’ai écrit aide d’autres personnes
psanford/sqlite3vfs
SQLite fonctionne comme d’habitude, et Litestream opère de manière transparente par-dessus
Autrement dit, on peut mettre en place une restauration à un instant donné (PITR) uniquement avec SQL et les pragma SQLite.
On peut consulter rapidement des données passées sans toucher directement au dataset de production
Il suffit de définir le bucket S3 via une variable d’environnement, puis dans SQLite de faire
.load litestream.soetavec
PRAGMA litestream_time = '5 minutes ago';on peut consulter directement les données à un instant passébrew install sqlite3,il faut indiquer explicitement le nom de la fonction d’initialisation comme dans
.load litestream sqlite3_litestreamvfs_initIl suffit de définir
"LITESTREAM_REPLICA_URL"et les variables d’environnement des clés AWSAprès avoir chargé l’extension avec
temp.loadExtension("/path/to/litestream.dylib", "sqlite3_litestreamvfs_init"),on peut l’utiliser immédiatement en ouvrant
file:my.db?vfs=litestream.dylibMon cas d’usage consiste à utiliser directement sur un site web une base SQLite en lecture seule stockée sur S3
La base est mise à jour via une tâche cron, etc., et le site ne fait que lire les données les plus récentes via Litestream VFS
Je me demande si ce type d’usage est acceptable, et s’il existe aussi un module d’intégration Python
Pour l’instant, mon appli Flask récupère les données depuis Google Spreadsheet, les convertit en SQLite puis les met à jour chaque jour
Voir le code de mon appli
Ça fonctionne tel quel même dans le CLI SQLite, sans code Python supplémentaire
Il n’utilise que S3 comme dépendance externe et s’accorde bien avec SQLite
Référence sur les performances SQLite de ZeroFS
Exemple de code ncruces/go-sqlite3
On peut le piloter depuis le code du programme sans variable d’environnement, et gérer plusieurs bases en parallèle
Attention toutefois :
PRAGMA litestream_times’applique au niveau de la connexion, donc il faut faire attention si on utilise un pool de connexions.load litestream.so, j’ai immédiatement pensé à ncruces/go-sqlite3Je me demande si ça a été difficile de le faire fonctionner aussi dans un environnement wasm
L’extension “DuckLake” de DuckDB crée un snapshot à chaque transaction et fournit une fonction de “voyage temporel”
C’est similaire au PITR de Litestream VFS
En OLTP, on appelle cela une fonction de restauration, alors qu’en OLAP on parle de “Time Travel”
DuckLake s’appuie sur une base de catalogue externe (PostgreSQL/MySQL/SQLite) pour coordonner les accès multi-processus
Litestream, lui, permet à plusieurs lecteurs d’accéder simultanément via les fichiers LTX immuables sur S3
Dans les deux mondes, on converge vers une structure de type “stockage partagé + métadonnées + compaction”
J’aimerais voir davantage de collaboration croisée entre ce genre de projets
Notes de version v0.5.3
Par exemple, si on utilise des extensions de recherche vectorielle comme sqlite-vec ou vss,
est-ce qu’on peut faire des sauvegardes en temps réel vers S3 avec Litestream puis interroger à distance via Litestream VFS ?
J’imagine qu’il n’y a pas d’autre choix que de le tester directement