197 votes

Comment "EXPIRE" la clé enfant "HSET" dans redis ?

J'ai besoin d'expirer toutes les clés dans le hash redis, qui sont plus vieux que 1 mois.

5voto

Elon Musk va bientôt envoyer des gens sur la lune et nous ne pouvons toujours pas faire expirer les champs sur redis :(

Bref, la solution que j'ai trouvée est la suivante :

Disons que je veux que la date d'expiration soit fixée à toutes les 3 minutes : Donc je garde les données dans 3 champs 0 1 2. et ensuite je fais module% 3 à l'heure actuelle en minutes.

si le module par exemple == 0 alors j'utilise seulement 1, 2 et 0, je supprime ; puis il devient 1, donc j'utilise 2 et 0 et je supprime 1.

Je ne l'utilise pas et je ne l'ai pas vérifié mais je veux juste vous faire savoir que c'est possible.

4voto

Nikita Koksharov Points 1552

Il existe un Redisson framework java qui implémente le hash Map avec support TTL d'entrée. Il utilise hmap y zset Les objets Redis sous le capot. Exemple d'utilisation :

RMapCache<Integer, String> map = redisson.getMapCache('map');
map.put(1, 30, TimeUnit.DAYS); // this entry expires in 30 days

Cette approche est très utile.

4voto

rococo Points 436

Si votre cas d'utilisation est que vous mettez en cache des valeurs dans Redis et que vous êtes tolérant à l'égard des valeurs périmées, mais que vous souhaitez les rafraîchir de temps en temps afin qu'elles ne soient pas trop périmées, une solution de fortune consiste à inclure un horodatage dans la valeur du champ et à gérer les expirations à l'endroit où vous accédez à la valeur.

Cela vous permet de continuer à utiliser les hachages Redis normalement sans avoir à vous soucier des complications qui pourraient survenir avec les autres approches. Le seul coût est un peu de logique et d'analyse supplémentaires du côté du client. Ce n'est pas une solution parfaite, mais c'est ce que je fais généralement, car je n'ai pas eu besoin de TTL pour une autre raison et j'ai généralement besoin d'effectuer une analyse supplémentaire de la valeur mise en cache de toute façon.

Donc, en gros, ce sera quelque chose comme ça :

Dans Redis :

hash_name
- field_1: "2021-01-15;123"
- field_2: "2021-01-20;125"
- field_2: "2021-02-01;127"

Votre (pseudo)code :

val = redis.hget(hash_name, field_1)
timestamp = val.substring(0, val.index_of(";"))

if now() > timestamp:
  new_val = get_updated_value()
  new_timestamp = now() + EXPIRY_LENGTH
  redis.hset(hash_name, field_1, new_timestamp + ";" + new_val)
  val = new_val
else:
  val = val.substring(val.index_of(";"))

// proceed to use val

Le plus gros problème, c'est que vous ne supprimez jamais de champs et que le hachage peut devenir très important. Je ne suis pas sûr qu'il y ait une solution élégante pour cela - j'ai l'habitude de supprimer le hachage de temps en temps s'il me semble trop grand. Peut-être que vous pourriez garder une trace de tout ce que vous avez stocké quelque part et les supprimer périodiquement (bien qu'à ce stade, vous pourriez tout aussi bien utiliser ce mécanisme pour expirer les champs manuellement...).

3voto

En ce qui concerne l'implémentation NodeJS, j'ai ajouté une fonction personnalisée expiryTime dans l'objet que je sauvegarde dans le HASH. Ensuite, après une période de temps spécifique, j'efface les entrées expirées du HASH en utilisant le code suivant :

client.hgetall(HASH_NAME, function(err, reply) {
    if (reply) {
        Object.keys(reply).forEach(key => {
            if (reply[key] && JSON.parse(reply[key]).expiryTime < (new Date).getTime()) {
                client.hdel(HASH_NAME, key);
            }
        })
    }
});

2voto

msoliman Points 732

Vous pouvez stocker les clés/valeurs dans Redis différemment pour atteindre cet objectif, en ajoutant simplement un préfixe ou un espace de nom à vos clés lorsque vous les stockez, par exemple "hset_".

  • Obtenir une clé/valeur GET hset_key est égal à HGET hset key

  • Ajouter une clé/valeur SET hset_key value est égal à HSET hset key

  • Obtenir toutes les clés KEYS hset_* est égal à HGETALL hset

  • Obtenir tous les vals devrait être fait en 2 opérations, d'abord obtenir toutes les clés. KEYS hset_* puis récupérer la valeur de chaque clé

  • Ajouter une clé/valeur avec TTL ou expiration qui est le sujet de la question :

    SET hset_key value EXPIRE hset_key

Nota : KEYS va chercher la clé correspondante dans toute la base de données, ce qui peut affecter les performances, surtout si la base de données est importante.

Nota:

  • KEYS recherchera la clé correspondante dans toute la base de données, ce qui peut affecter les performances, surtout si vous avez une grande base de données. alors que SCAN 0 MATCH hset_* pourrait être meilleur tant qu'il ne bloque pas le serveur, mais les performances restent un problème en cas de base de données importante.

  • Vous pouvez créer une nouvelle base de données pour stocker séparément ces clés que vous voulez faire expirer, surtout s'il s'agit d'un petit ensemble de clés.

Merci à @DanFarrell qui a mis en évidence le problème de performance lié à KEYS

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