La version 1.2 de RedisTimeSeries est arrivée !

La version 1.2 de RedisTimeSeries est arrivée !

Quand on y pense, “la vie est une série chronologique”.

Alors peut-être ne devrait-il pas être surprenant que même si le Module RedisTimeSeries-qui ssimplifie l’utilisation de Redis pour les cas d’utilisation de séries chronologiques comme l’IoT, la surveillance des applications et la télémétriea été généralement disponible uniquement depuis juin 2019, nous voyons déjà un grand nombre de cas d’utilisation intéressants. Par exemple, le New York Times utilise RedisTimeSeries dans sa version interne Projet Photon, tout comme Amazon Web Service Greengrass IdO projet (voir le dépôt GitHub ici).

Mais nous ne sommes pas là pour nous reposer sur nos lauriers. Au lieu de cela, nous annonçons la disponibilité générale d’une nouvelle version majeure du module, RedisTimeSeries 1.2, qui fait ses débuts avec un longue liste de nouvelles fonctionnalités puissantes. Mais compte tenu de l’intérêt généralisé, notre objectif principal pour RedisTimeSeries 1.2 était d’augmenter la convivialité sans dégrader les performances. Étant donné que Redis est une base de données en mémoire, le stockage d’un grand volume de données de séries chronologiques dans la DRAM peut devenir coûteux. Ainsi, dans la version 1.2, nous avons ajouté une compression qui réduit ses besoins en mémoire jusqu’à 90 % dans la plupart des scénarios – en théorie, cela pourrait compressez vos données de séries chronologiques jusqu’à 98 % ! Nous avons rendu notre API plus cohérente et intuitive, et supprimé les données de réponse redondantes pour améliorer encore les performances. Ensemble, l’API change et la compression s’améliore performances de lecture jusqu’à 70 %. Mettez tout cela ensemble et la nouvelle version de RedisTimeSeries pourrait faire économiser beaucoup d’argent aux utilisateurs sur les coûts d’infrastructure sans affecter les performances.

(Consultez notre article de blog associé sur Repères RedisTimeSeries 1.2 pour plus d’informations sur la façon le débit d’ingestion est indépendant du nombre de séries chronologiques dans l’ensemble de données, de la compression et du nombre d’échantillons dans une série chronologique.)

Mais commençons par le fonctionnement de la compression, car c’est plutôt cool.

Gorille compression

Une série chronologique dans RedisTimeSeries consiste en une liste chaînée de blocs contenant chacun un nombre fixe d’échantillons. Un échantillon est un tuple d’un horodatage et d’une valeur représentant une mesure à un instant précis. L’heure est représentée par un horodatage et la valeur par un nombre flottant (format à virgule flottante double précision). Les morceaux eux-mêmes sont indexés dans un arbre Radix. Vous pouvez en savoir plus sur les internes ici.

Non compressés, l’horodatage et la valeur consomment chacun 8 octets (ou 16 octets/128 bits au total) pour chaque échantillon. Pour les horodatages, nous utilisons la compression double delta et pour les valeurs que nous utilisons XOR (“Exclusif ou”) compression. Les deux techniques sont basées sur la Papier Facebook Gorille et sont documentés dans notre code sourcemais nous expliquerons comment cela fonctionne ci-dessous.

Encodage double delta de l’horodatage

Dans de nombreux cas d’utilisation de séries chronologiques, les échantillons sont collectés à intervalles fixes. Imaginez que nous collectons des mesures à partir d’un capteur de température toutes les 5 secondes. En millisecondes, le delta entre deux échantillons consécutifs serait de 5 000. Parce que les intervalles restent constants, cependant, le delta entre deux deltas—le double delta— serait 0.

image2

Parfois, les données arrivent à la seconde 6 ou à la seconde 4, mais c’est généralement l’exception. Plutôt que de stocker ce ΔΔ (double-delta) dans son intégralité en 64 bits, encodage à longueur variable est utilisé selon le pseudo code suivant :

If ΔΔ is zero, then store a single ‘0’ bit
Else If ΔΔ is between [-63, 64], store ‘10’ followed by the value (7 bits)
Else If ΔΔ is between [-512,511], store ‘110’ followed by the value (10 bits)
Else if ΔΔ is between [-4096,4095], store ‘1110’ followed by the value (13 bits)
Else if ΔΔ is between [-32768,32767], store ‘11110’ followed by the value (16 bits)
Else store ‘11111’ followed by D using 64 bits

Compression XOR de la valeur

La base de la compression de valeur est l’hypothèse que la différence entre les valeurs consécutives est généralement faible et se produit progressivement au lieu de brusquement. De plus, les flottants sont intrinsèquement inutiles et contiennent de nombreux zéros répétés qui peuvent être éliminés. Ainsi, lorsque deux valeurs consécutives sont XOR, seuls quelques bits significatifs seront présents dans le résultat. Pour plus de simplicité, l’exemple ci-dessous utilise un double simple précision—RedisTimeSeries utilise des doubles double précision :

image3

Vous pouvez voir que l’opération XOR entre les deux premiers nombres égaux est, évidemment, 0. Mais il y a aussi souvent un certain nombre de 0 de début et de fin autour du valeur XOR significative. Le codage à longueur variable des différences XOR des valeurs supprime les zéros de début et de fin.

Il existe également un bit de contrôle qui peut encore réduire le nombre de bits consommés par un échantillon. Si le bloc de bits significatifs tombe dans le bloc de la valeur précédente bits significatifsc’est-à-dire qu’il y a au moins autant de zéros de tête et autant de zéros de fin que dans la valeur précédente, alors le nombre de zéros de tête et de fin de l’échantillon précédent peut être utilisé :

If XOR is zero (same value)
store single ‘0’ bit 
Else 
calculate the number of leading and trailing zeros in the XOR
store bit ‘1’ followed by
If the block of meaningful bits falls within the block of previous meaningful bits, 
store control bit `0`
Else store control bit `1`
store the length of the number of leading zeros in the next 5 bits, 
store the length of the meaningful XOR value in the next 6 bits. 
Finally store the meaningful bits of the XOR value.

Consommation de mémoire résultante

Alors, combien de réduction de mémoire cette technique peut-elle vous apporter ? Sans surprise, la réduction réelle dépend de votre cas d’utilisation, mais nous avons remarqué une réduction de 94 % dans nos ensembles de données de référence. Selon la page six de Facebook Papier gorille, chaque échantillon consomme en moyenne 1,37 octets, contre 16 octets. Cela se traduit par une 90% de réduction de mémoire pour les cas d’utilisation les plus courants.

La limite théorique est atteinte lorsque le double-delta vaut 0 et que le XOR vaut également 0. Dans ce cas, chaque échantillon utilise 2 bits au lieu de 128, d’où une réduction de la mémoire de 98,4 % ! Dans le pire des cas, un échantillon consomme 145 bits : 69 bits pour l’horodatage et 76 bits pour la valeur. (Pour que ce cas extrême se produise, le double delta devrait être supérieur à MAX_32 et les valeurs flottantes seraient extrêmement complexes et différentes. Parce que nous ne voulons pas exclure même les cas d’utilisation extrêmes, vous pouvez toujours utiliser le Option `NON COMPRIMÉ` lorsque vous créez une série chronologique.)

Améliorations de l’API

Les cas d’utilisation de séries chronologiques sont principalement des ajouts uniquement, ce qui permet des optimisations telles que la compression décrite ci-dessus. Mais avec cette approche de compression, l’insertion d’un échantillon avec un horodatage antérieur au dernier échantillon introduira non seulement une logique plus complexe et consommera plus de cycles CPU, mais nécessitera également une gestion de la mémoire plus complexe.

C’est pourquoi avec RedisTimeSeries 1.2, nous avons rendu l’API plus stricte et n’autorisons plus les clients à réécrire le dernier échantillon de la série temporelle. Cela peut sembler limité, mais la plupart des changements sont intuitifs et améliorent en fait l’expérience du développeur.

En conséquence, le calcul automatique de l’échantillon agrégé pour un sous-échantillonné la série chronologique se produit maintenant à la série chronologique source. Ce n’est que lorsque la fenêtre temporelle d’agrégation est passée que l’échantillon représentant l’agrégation sera écrit dans la série chronologique sous-échantillonnée. Cela signifie que les écritures se produisent moins souvent dans la série chronologique sous-échantillonnée, ce qui améliore encore les performances d’ingestion.

Avec le sous-échantillonnage, vous pouvez réduire votre consommation de mémoire en agrégeant des échantillons qui se trouvent plus loin dans le passé. Mais vous pouvez également modéliser des compteurs pour des fenêtres horaires de tailles fixes, par exemple le nombre de pages vues du site Web par heure. Vous pouvez facilement construire ces compteurs avec RedisTimeSeries. Dans la série chronologique source, vous utilisez TS.ADD pour ajouter un échantillon avec la valeur que vous souhaitez que le compteur soit incrémenté et une règle de sous-échantillonnage avec un somme agrégation sur la taille de fenêtre fixe :

redis:6379> TS.CREATE ts RETENTION 20000
OK
redis:6379> TS.CREATE counter
OK
redis:6379> TS.CREATERULE ts counter AGGREGATION sum 5000
OK
redis:6379> TS.ADD ts * 5
(integer) 1580394077750
redis:6379> TS.ADD ts * 2
(integer) 1580394079257
redis:6379> TS.ADD ts * 3
(integer) 1580394085716
redis:6379> TS.RANGE counter - +
1) 1) (integer) 1580394075000
   2) "7"
redis:6379> TS.ADD ts * 1
(integer) 1580394095233
redis:6379> TS.RANGE counter - +
1) 1) (integer) 1580394075000
   2) "7"
2) 1) (integer) 1580394085000
   2) "3"
redis:6379> TS.RANGE ts - +
1) 1) (integer) 1580394077750
   2) "5"
2) 1) (integer) 1580394079257
   2) "2"
3) 1) (integer) 1580394085716
   2) "3"
4) 1) (integer) 1580394095233
   2) "1"
redis:6379>

Dans les deux cas, la série sous-échantillonnée aura le compteur exact que vous recherchez.

Quelle est la prochaine étape pour RedisTimeSeries ?

L’ajout de la compression Gorilla et des améliorations de l’API a considérablement réduit la consommation de mémoire. (Pour plus d’informations sur la façon dont cela fonctionne, voir the article de blog associé sur les benchmarks RedisTimeSeries 1.2.)

Mais nous n’avons pas encore fini. À l’avenir, nous prévoyons de remplacer l’indexation secondaire propriétaire RedisTimeSeries à l’aide d’ensembles triés par la nouvelle API de bas niveau utilisée dans RediRecherche. Cela permettra aux utilisateurs d’effectuer des requêtes de recherche en texte intégral sur les étiquettes liées à la série chronologique à l’aide d’un langage de requête riche et éprouvé. Nous travaillons également à compléter notre API pour être en ligne avec les autres structures de données Redis en introduisant le TS.REVRANGE et TS.MREVRANGE commandes.

La plupart des modules Redis se concentrent sur la résolution d’un problème particulier extrêmement bien et extrêmement rapidement – leur combinaison permet un large éventail de nouveaux cas d’utilisation intéressants. Nous explorons actuellement la combinaison de RedisTimeSeries et RedisAI pour effectuer une détection d’anomalies en temps réel et un apprentissage non supervisé. Enfin, nous travaillons à exposer une API de bas niveau pour RedisGears qui vous permettra d’effectuer une agrégation de séries chronologiques croisées de la manière la plus performante.

Development Source

Related Posts

RLEC 4.2.1 apporte des contrôles granulaires à la haute disponibilité et aux performances

RLEC 4.2.1 apporte des contrôles granulaires à la haute disponibilité et aux performances

Comment HolidayMe utilise Redis Enterprise comme base de données principale

Comment HolidayMe utilise Redis Enterprise comme base de données principale

Annonce de RedisGears 1.0 : un moteur sans serveur pour Redis

Annonce de RedisGears 1.0 : un moteur sans serveur pour Redis

Clés Redis dans la RAM |  Redis

Clés Redis dans la RAM | Redis

No Comment

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *