Risposte:
Questo non è possibile , per mantenere Redis semplice .
Disse Antirez, creatore di Redis:
Salve, non è possibile, utilizzare una chiave di primo livello diversa per quel campo specifico o memorizzare insieme al campo un altro campo con una scadenza, recuperarli entrambi e lasciare che l'applicazione capisca se è ancora valido o non basato su ora attuale.
Redis non supporta TTL
hash diversi dalla chiave in alto, che farebbero scadere l'intero hash. Se stai usando un cluster sharded, c'è un altro approccio che potresti usare. Questo approccio potrebbe non essere utile in tutti gli scenari e le caratteristiche delle prestazioni potrebbero differire da quelle previste. Vale ancora la pena menzionare:
Quando si ha un hash, la struttura sostanzialmente assomiglia a:
hash_top_key
- child_key_1 -> some_value
- child_key_2 -> some_value
...
- child_key_n -> some_value
Dato che vogliamo aggiungere TTL
alle chiavi figlio, possiamo spostarle nelle chiavi superiori. Il punto principale è che la chiave ora dovrebbe essere una combinazione di hash_top_key
e chiave figlio:
{hash_top_key}child_key_1 -> some_value
{hash_top_key}child_key_2 -> some_value
...
{hash_top_key}child_key_n -> some_value
Stiamo usando la {}
notazione apposta. Ciò consente a tutte quelle chiavi di cadere nella stessa hash slot
. Puoi leggere di più al riguardo qui: https://redis.io/topics/cluster-tutorial
Ora se vogliamo fare la stessa operazione di hash, potremmo fare:
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
Quello interessante qui è HGETALL
. Per prima cosa otteniamo le hash slot
chiavi di tutti i nostri figli. Quindi otteniamo le chiavi per quel particolare hash slot
e infine recuperiamo i valori. Dobbiamo stare attenti qui poiché potrebbero esserci più di n
chiavi per quello hash slot
e potrebbero anche esserci chiavi a cui non siamo interessati ma hanno lo stesso hash slot
. Potremmo effettivamente scrivere uno Lua
script per eseguire questi passaggi nel server eseguendo un comando EVAL
o EVALSHA
. Ancora una volta, è necessario prendere in considerazione le prestazioni di questo approccio per il proprio scenario particolare.
Qualche altro riferimento:
Esiste un framework Java Redisson che implementa Map
oggetti hash con supporto TTL di ingresso. Usa hmap
e zset
Redis oggetti sotto il cofano. Esempio di utilizzo:
RMapCache<Integer, String> map = redisson.getMapCache('map');
map.put(1, 30, TimeUnit.DAYS); // this entry expires in 30 days
Questo approccio è molto utile.
Questo è possibile in KeyDB che è un fork di Redis. Poiché è una forcella è completamente compatibile con Redis e funziona come una sostituzione.
Usa semplicemente il comando EXPIREMEMBER. Funziona con set, hash e set ordinati.
EXPIREMEMBER sottochiave nome chiave [ora]
Puoi anche usare TTL e PTTL per vedere la scadenza
Sottochiave nome chiave TTL
Ulteriore documentazione è disponibile qui: https://docs.keydb.dev/docs/commands/#expiremember
Per quanto riguarda un'implementazione di NodeJS, ho aggiunto un expiryTime
campo personalizzato nell'oggetto che salvo nell'HASH. Quindi, dopo un periodo di tempo specifico, cancello le voci HASH scadute utilizzando il seguente codice:
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);
}
})
}
});
Array.filter
per creare un array di keys
per eliminare dall'hash e poi passarlo a client.hdel(HASH_NAME, ...keys)
in una singola chiamata.
const keys = Object.keys(reply).filter(key => reply[key] && JSON.parse(reply[key]).expiryTime < Date.now()); client.hdel(HASH_NAME, ...keys);
Puoi. Ecco un esempio.
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
Utilizzare EXPIRE o EXPIREAT comando.
Se vuoi far scadere chiavi specifiche nell'hash più vecchie di 1 mese. Non è possibile. Il comando Redis expire è per tutte le chiavi nell'hash. Se imposti la chiave hash giornaliera, puoi impostare un tempo per le chiavi in cui vivere.
hset key-20140325 f1 1
expire key-20140325 100
hset key-20140325 f1 2
Puoi memorizzare chiave / valori in Redis in modo diverso per ottenere ciò, semplicemente aggiungendo un prefisso o uno spazio dei nomi alle tue chiavi quando le memorizzi, ad esempio "hset_"
Ottieni una chiave / valore GET hset_key
uguale aHGET hset key
Aggiungi una chiave / valore SET hset_key value
uguale aHSET hset key
Ottieni tutte le chiavi KEYS hset_*
uguali aHGETALL hset
Ottieni tutte le vals dovrebbe essere fatto in 2 operazioni, prima ottieni tutte le chiavi KEYS hset_*
quindi ottieni il valore per ogni chiave
Aggiungi una chiave / valore con TTL o fai scadere che è l'argomento della domanda:
SET hset_key value
EXPIRE hset_key
Nota : KEYS
cercherà la corrispondenza della chiave nell'intero database che potrebbe influire sulle prestazioni, specialmente se si dispone di un database di grandi dimensioni.
Nota:
KEYS
cercherà la corrispondenza della chiave nell'intero database che potrebbe influire sulle prestazioni soprattutto se si dispone di un database di grandi dimensioni. mentre SCAN 0 MATCH hset_*
potrebbe essere migliore fintanto che non blocca il server, ma le prestazioni sono comunque un problema in caso di database di grandi dimensioni.
È possibile creare un nuovo database per archiviare separatamente queste chiavi che si desidera far scadere, soprattutto se sono piccoli set di chiavi.
Grazie a @DanFarrell che ha evidenziato il problema delle prestazioni relativo a
KEYS
hashset
.. ottieni O (1) imposta O (1) ottieni tutto O (n)
O(n)
per il numero di cose nel set, KEYS
per il numero di cose nel DB.
scan 0 match namespace:*
potrebbe essere migliore fintanto che non blocca il server
Abbiamo avuto lo stesso problema discusso qui.
Abbiamo un hash Redis, una chiave per le voci hash (coppie nome / valore) e dovevamo mantenere i tempi di scadenza individuali su ogni voce hash.
Lo abbiamo implementato aggiungendo n byte di dati di prefisso contenenti informazioni di scadenza codificate quando scriviamo i valori della voce hash, abbiamo anche impostato la scadenza della chiave nel momento contenuto nel valore che viene scritto.
Quindi, in lettura, decodifichiamo il prefisso e controlliamo la scadenza. Questo è un sovraccarico aggiuntivo, tuttavia, le letture sono ancora O (n) e l'intera chiave scadrà quando l'ultima voce hash è scaduta.
È possibile utilizzare le notifiche di Redis Keyspace utilizzando psubscribe
e "__keyevent@<DB-INDEX>__:expired"
.
Con ciò, ogni volta che una chiave scadrà, riceverai un messaggio pubblicato sulla tua connessione redis.
Per quanto riguarda la tua domanda fondamentalmente crei una chiave "normale" temporanea utilizzando set
un tempo di scadenza in s / ms. Dovrebbe corrispondere al nome della chiave che desideri eliminare nel tuo set.
Poiché la tua chiave temporanea verrà pubblicata sulla tua connessione redis tenendo premuto il tasto "__keyevent@0__:expired"
quando è scaduta, puoi facilmente eliminare la tua chiave dal set originale poiché il messaggio avrà il nome della chiave.
Un semplice esempio pratico su quella pagina: https://medium.com/@micah1powell/using-redis-keyspace-notifications-for-a-reminder-service-with-node-c05047befec3
doc: https://redis.io/topics/notifications (cerca il flag xE)
Puoi utilizzare Sorted Set in redis per ottenere un contenitore TTL con timestamp come punteggio. Ad esempio, ogni volta che si inserisce una stringa di evento nel set, è possibile impostarne il punteggio sull'ora dell'evento. In questo modo puoi ottenere dati di qualsiasi finestra temporale chiamando
zrangebyscore "your set name" min-time max-time
Inoltre, possiamo fare scadere utilizzando zremrangebyscore "your set name" min-time max-time
per rimuovere vecchi eventi.
L'unico inconveniente qui è che devi fare le pulizie da un processo esterno per mantenere le dimensioni del set.
Puoi far scadere gli hash Redis facilmente, ad esempio usando python
import redis
conn = redis.Redis('localhost')
conn.hmset("hashed_user", {'name': 'robert', 'age': 32})
conn.expire("hashed_user", 10)
Questo farà scadere tutte le chiavi figlio in hash hashed_user dopo 10 secondi
lo stesso da 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"
dopo 10 secondi
127.0.0.1:6379> hgetall testt
(empty list or set)
hset
bambino, non il pieno hset
.