2 votes

Redis : Comment compter les éléments d'un flux dans un certain intervalle ?

Objectif de l'entreprise

Je suis en train de créer un tableau de bord qui dépendra de certaines séries temporelles et je vais utiliser Redis pour le mettre en œuvre. Je suis nouveau dans l'utilisation de Redis et j'essaie d'utiliser Redis-Streams pour compter les éléments dans un flux.

XADD conversation:9:chat_messages * id 2583 user_type Bot
XADD conversation:9:chat_messages * id 732016 user_type User
XADD conversation:9:chat_messages * id 732017 user_type Staff
XRANGE conversation:9:chat_messages - +

Je sais que je peux obtenir le nombre total d'éléments en utilisant la commande XLEN comme ceci :

XLEN conversation:9:chat_messages

mais je veux aussi connaître les éléments d'une période, par exemple :

XLEN conversation:9:chat_messages 1579551316273 1579551321872

Je sais que je peux utiliser LUA pour compter ces éléments mais je veux un moyen VRAIMENT rapide d'y parvenir et je sais que l'utilisation du balisage Redis sera le moyen le plus rapide.

Y a-t-il un moyen d'y parvenir avec une commande Redis directe ? Ou dois-je écrire un script Lua pour le faire ?

Informations complémentaires

Je suis limité par ElastiCache d'AWS à l'utilisation du seul Redis 5.0.6, je ne peux pas installer d'autres modules tels que les RedisTimeSeries module. J'aimerais utiliser ce module mais ce n'est pas possible pour le moment.

3voto

Itamar Haber Points 2317

Bien que la structure de données Redis Stream ne supporte pas cela, vous pouvez utiliser un Sorted Set à côté pour garder la trace des plages de messages.

Fondamentalement, pour chaque ID de message que vous obtenez de XADD - par exemple "1579551316273-0" - vous devez faire un ZADD conversation:9:ids 0 1579551316273-0 . Ensuite, vous pouvez utiliser ZLEXCOUNT pour obtenir la "longueur" d'une plage.

1voto

LeoMurillo Points 4117

Désolé, il n'y a pas de méthode commandée pour y parvenir.

Votre meilleure option avec Redis Streams serait d'utiliser un script Lua. Vous obtiendrez O(N), N étant le nombre d'éléments comptés, au lieu de O(log N) si une commande existait.

local T = redis.call('XRANGE', KEYS[1], ARGV[1], ARGV[2])
local count = 0
for _ in pairs(T) do count = count + 1 end
return count

Notez que la différence entre O(N) et O(log(N)) est significative pour un grand N, mais pour une application de chat, si elle est suivie par conversation, cela ne fera pas une si grande différence si les chats ont des centaines ou même des milliers d'entrées, une fois que vous comptez le temps de commande total, y compris le temps de trajet aller-retour qui prend la plupart du temps. Le script Lua ci-dessus supprime la charge réseau et le temps de traitement du client.

Vous pouvez passer à des ensembles triés si vous voulez vraiment O(log N) et que vous n'avez pas besoin de groupes de consommateurs et d'autres caractéristiques de flux. Voir Comment stocker dans Redis un ensemble trié avec un timestamp côté serveur comme score ? si vous voulez utiliser le timestamp du serveur Redis de manière atomique.

Vous pouvez alors utiliser ZCOUNT qui est O(log(N)).

Si vous avez besoin des fonctions d'étirement, vous devez conserver l'ensemble trié comme index secondaire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X