Construire une base de données de séries temporelles depuis zéro
(nakabonne.dev)-
Écrit en Go, mais les concepts sont presque indépendants du langage
-
Les données de séries temporelles sont une collection de plusieurs valeurs associées à des horodatages. Chaque élément est un point de données
→ Le volume est important. Elles n’ont de sens que lorsqu’il y en a beaucoup. Il est fréquent d’en capturer un million par seconde
→ Append-only, triées par ordre chronologique, priorité aux données récentes
→ Lecture en masse sur des unités de temps spécifiques
→ High Cardinality (taille des ensembles très élevée)
→ La plupart des usages lisent surtout les données récentes
-
Une bibliothèque de moteur de base de données TStorage, conçue principalement pour des charges à forte écriture sur des données de séries temporelles, a été développée en Go
-
Modèle de données
→ Modèle de données linéaire
→ Partitionnement des points de données par unité de temps
→ Chaque partition fonctionne comme une base de données distincte et indépendante contenant toutes les données de cette période
→ Possibilité de modifier pour que seule la tête et la partition suivante soient des partitions mémoire stockées sur le heap
→ Écriture préalable dans un WAL (Write Ahead Log) avant l’écriture effective afin d’éviter la perte de données
→ Les données des partitions antérieures sont stockées sur disque dans un fichier unique. Les partitions disque sont en lecture seule
- Partition mémoire
→ La liste des points de données est représentée sur le heap sous forme de tableau (semblable aux slices de Go)
→ À cause de la latence et de la synchronisation, l’out-of-order se produit souvent. Si cela reste dans la même partition, on peut réordonner au moment du stockage via un buffer ; si cela concerne une autre partition, c’est possible en l’ajoutant après une partition précédente qui n’est pas la tête
→ Les mêmes données que celles réellement enregistrées dans le WAL sont stockées afin de permettre la récupération en cas d’erreur
- Partition disque
→ Pour chaque partition, un répertoire stocke les métadonnées et les données réelles compressées (version réduite du Prometheus V3 Storage)
→ Format de données memory-mapped (pouvant être mis en cache via mmap par le noyau)
→ Les métadonnées, au format JSON, servent à former l’index
- L’encodage des données, représentées sous forme de tuples horodatage/valeur, utilise la méthode proposée dans l’article Gorilla de Facebook
→ Les horodatages et les valeurs sont encodés par des méthodes différentes
→ timestamp est une valeur entière non signée sur 64 bits utilisant un encodage Delta-of-delta
✓ Encodage Delta : méthode consistant à n’enregistrer que la différence entre la valeur précédente et la valeur actuelle
✓ Encodage Delta-of-Delta : comme elles apparaissent généralement à intervalles temporels réguliers, on n’enregistre que le delta du delta
✓ Comme l’encodage est de longueur variable, Delta-of-Delta utilise le moins d’espace
→ values est une valeur flottante signée sur 64 bits utilisant un encodage XOR
✓ La première valeur est simplement stockée
✓ La valeur suivante est XORée ; si le résultat vaut 0, elle est identique à la précédente, donc un seul bit 0 est stocké
✓ Si le résultat n’est pas 0, le calcul se base sur les autres bits (Meaningful Bit)
✓ On calcule les zéros en tête et en fin ; si leur nombre est identique, on ne stocke que 0 et les bits significatifs, sinon on stocke le nombre de zéros de tête, le nombre de Meaningful Bit et leur contenu
Aucun commentaire pour le moment.