web-dev-qa-db-fra.com

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

Je dois expirer toutes les clés de redis hash, qui sont plus vieilles que 1 mois.

63
aieven

Cela n’est pas possible , dans l’intérêt de garder Redis simple .

Quoth Antirez, créateur de Redis:

Bonjour, ce n'est pas possible, utilisez une clé de niveau supérieur différente pour cela champ spécifique, ou stocker avec le champ déposé un autre champ avec un expirer le temps, aller chercher les deux, et laisser l'application comprendre si c'est toujours valable ou non basé sur l'heure actuelle.

83
Supr

Il existe un framework Redisson Java qui implémente un objet hash Map avec le support d'entrée TTL Il utilise les objets hmap et zset 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.

3
Nikita Koksharov

Pour ce faire, vous pouvez stocker les clés/valeurs dans Redis différemment, en ajoutant simplement un préfixe ou un espace de noms à vos clés lorsque vous les stockez, par exemple. "hset_"

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

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

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

  • Obtenir toutes les valeurs doit être effectué en 2 opérations, obtenir d’abord toutes les clés KEYS hset_*, puis obtenir la valeur de chaque clé. 

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

 SET hset_key value
 EXPIRE hset_key

Remarque : KEYS recherchera la correspondance de la clé dans toute la base de données, ce qui peut affecter les performances, en particulier si vous avez une grande base de données. 

Remarque: 

  • KEYS recherchera la correspondance de la clé dans toute la base de données, ce qui peut affecter les performances, en particulier si vous avez une grande base de données. Alors que SCAN 0 MATCH hset_* pourrait être préférable tant qu’il ne bloque pas le serveur mais que les performances restent un problème pour les bases de données volumineuses. 

  • Vous pouvez créer une nouvelle base de données pour stocker séparément ces clés que vous voulez expirer, en particulier s’il s’agit d’un petit jeu de clés.

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

1
msoliman

Vous pouvez expirer Redis hachez facilement, par exemple en utilisant python

import redis
conn = redis.Redis('localhost')
conn.hmset("hashed_user", {'name': 'robert', 'age': 32})
conn.expire("hashed_user", 10)

Ceci expirera toutes les clés enfant dans hash hashed_user après 10 secondes

idem de redis-cli,

127.0.0.1:6379> HMSET testt username wlc password P1pp0 age 34
OK
127.0.0.1:6379> hgetall testt
1) "username"
2) "wlc"
3) "password"
4) "P1pp0"
5) "age"
6) "34"
127.0.0.1:6379> expire testt 10
(integer) 1
127.0.0.1:6379> hgetall testt
1) "username"
2) "wlc"
3) "password"
4) "P1pp0"
5) "age"
6) "34"

après 10 secondes

127.0.0.1:6379> hgetall testt
(empty list or set)
1
Thomas John

En ce qui concerne une implémentation de NodeJS, j'ai ajouté un champ expiryTime personnalisé dans l'objet que j'enregistre dans le hachage. Puis, après une période donnée, j'efface les entrées HASH expirées à l'aide du 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);
            }
        })
    }
});
1

Redis ne prend pas en charge l’ajout de TTL sur des hachages autres que la touche supérieure, ce qui expirerait tout le hachage. Si vous utilisez un cluster partagé, vous pouvez utiliser une autre approche. Cette approche pourrait ne pas être utile dans tous les scénarios et les caractéristiques de performance pourraient différer de celles attendues. Encore à noter:

Lorsque vous avez un hachage, la structure ressemble en gros à:

hash_top_key
  - child_key_1 -> some_value
  - child_key_2 -> some_value
  ...
  - child_key_n -> some_value

Puisque nous voulons ajouter TTL aux clés enfants, nous pouvons les déplacer en haut des clés. Le point principal est que la clé devrait maintenant être une combinaison de hash_top_key et de clé enfant:

{hash_top_key}child_key_1 -> some_value
{hash_top_key}child_key_2 -> some_value
...
{hash_top_key}child_key_n -> some_value

Nous utilisons la notation {} à dessein. Cela permet à toutes ces clés de tomber dans le même hash slot. Vous pouvez en lire plus à ce sujet ici: https://redis.io/topics/cluster-tutorial

Maintenant, si nous voulons faire la même opération de hachage, nous pourrions faire:

HDEL hash_top_key child_key_1 => DEL {hash_top_key}child_key_1

HGET hash_top_key child_key_1 => GET {hash_top_key}child_key_1

HSET hash_top_key child_key_1 some_value => SET {hash_top_key}child_key_1 some_value [some_TTL]

HGETALL hash_top_key => 
  keyslot = CLUSTER KEYSLOT {hash_top_key}
  keys = CLUSTER GETKEYSINSLOT keyslot n
  MGET keys

Ce qui est intéressant ici est HGETALL. Nous obtenons d’abord le hash slot pour toutes les clés de nos enfants. Ensuite, nous obtenons les clés pour ce hash slot et enfin, nous récupérons les valeurs. Nous devons faire attention ici car il pourrait y avoir plus que n clés pour ce hash slot et il pourrait aussi y avoir des clés qui ne nous intéressent pas mais qui ont le même hash slot. Nous pourrions en fait écrire un script Lua pour effectuer ces opérations sur le serveur en exécutant une commande EVAL ou EVALSHA. Encore une fois, vous devez prendre en compte les performances de cette approche pour votre scénario particulier.

Quelques autres références:

0
hveiga

Vous pouvez. Voici un exemple.

redis 127.0.0.1:6379> hset key f1 1
(integer) 1
redis 127.0.0.1:6379> hset key f2 2
(integer) 1
redis 127.0.0.1:6379> hvals key
1) "1"
2) "1"
3) "2"
redis 127.0.0.1:6379> expire key 10
(integer) 1
redis 127.0.0.1:6379> hvals key
1) "1"
2) "1"
3) "2"
redis 127.0.0.1:6379> hvals key
1) "1"
2) "1"
3) "2"
redis 127.0.0.1:6379> hvals key

Utilisez EXPIRE ou EXPIREAT command.

Si vous voulez expirer des clés spécifiques dans le hachage plus vieux que 1 mois. Cela n’est pas possible . La commande Redis expire concerne toutes les clés du hash . Si vous définissez une clé de hachage quotidienne, vous pouvez définir une durée de vie des clés.

hset key-20140325 f1 1
expire key-20140325 100
hset key-20140325 f1 2
0
Jonathan Kim

Vous pouvez utiliser Sorted Set in redis pour obtenir un conteneur TTL avec l'horodatage comme partition. Par exemple, chaque fois que vous insérez une chaîne d'événement dans le jeu, vous pouvez définir son score à l'heure de l'événement. Ainsi, vous pouvez obtenir des données de n'importe quelle fenêtre en appelant zrangebyscore "your set name" min-time max-time

De plus, nous pouvons faire expirer en utilisant zremrangebyscore "your set name" min-time max-time pour supprimer les anciens événements.

Le seul inconvénient ici est que vous devez faire le ménage à partir d'un processus externe pour conserver la taille de l'ensemble.

0
mojians

Vous pouvez utiliser les notifications Redis Keyspace en utilisant psubscribe et "__keyevent@<DB-INDEX>__:expired"

Avec cela, chaque fois qu'une clé expirera, vous obtiendrez un message publié sur votre connexion redis. 

En ce qui concerne votre question, vous créez essentiellement une clé "normale" temporaire en utilisant set avec un délai d'expiration en s/ms. Il doit correspondre au nom de la clé que vous souhaitez supprimer dans votre jeu. 

Comme votre clé temporaire sera publiée sur votre connexion redis contenant le "__keyevent@0__:expired" à son expiration, vous pouvez facilement supprimer votre clé de votre jeu d'origine car le message porte le nom de la clé. 

Un exemple simple en pratique sur cette page: https://medium.com/@micah1powell/using-redis-keyspace-notifications-for-a-reminder-service-with-node-c05047befec3

doc: https://redis.io/topics/notifications (recherchez le drapeau xE)

0
fas3r