Redis
 sql >> Database >  >> NoSQL >> Redis

come gestire la scadenza della sessione basandosi su redis?

Quindi è necessario che la tua applicazione venga notificata alla scadenza di una sessione in Redis.

Sebbene Redis non supporti questa funzione, ci sono una serie di trucchi che puoi utilizzare per implementarla.

Aggiornamento:dalla versione 2.8.0, Redis supporta questo http://redis.io/topics/notifications

Innanzitutto, le persone ci stanno pensando:questo è ancora in discussione, ma potrebbe essere aggiunto a una futura versione di Redis. Vedere i seguenti problemi:

  • https://github.com/antirez/redis/issues/83
  • https://github.com/antirez/redis/issues/594

Ora, ecco alcune soluzioni che puoi utilizzare con le attuali versioni di Redis.

Soluzione 1:patch Redis

In realtà, aggiungere una semplice notifica quando Redis esegue la scadenza della chiave non è così difficile. Può essere implementato aggiungendo 10 righe al file db.c del codice sorgente Redis. Ecco un esempio:

https://gist.github.com/3258233

Questa breve patch pubblica una chiave nell'elenco #scaduto se la chiave è scaduta e inizia con un carattere '@' (scelta arbitraria). Può essere facilmente adattato alle tue esigenze.

È quindi banale utilizzare i comandi EXPIRE o SETEX per impostare un tempo di scadenza per gli oggetti della sessione e scrivere un piccolo demone che esegue il loop su BRPOP per uscire dalla coda dall'elenco "#expired" e propagare la notifica nella tua applicazione.

Un punto importante è capire come funziona il meccanismo di scadenza in Redis. In realtà ci sono due differenti percorsi per la scadenza, entrambi attivi contemporaneamente:

  • Meccanismo pigro (passivo). La scadenza può verificarsi ogni volta che si accede a una chiave.

  • Meccanismo attivo. Un job interno campiona regolarmente (a caso) un certo numero di chiavi con scadenza impostata, cercando di trovare quelle in scadenza.

Nota che la patch sopra funziona bene con entrambi i percorsi.

La conseguenza è che il tempo di scadenza di Redis non è accurato. Se tutte le chiavi sono scadute, ma solo una sta per scadere e non è possibile accedervi, il processo di scadenza attivo potrebbe richiedere diversi minuti per trovare la chiave e farla scadere. Se hai bisogno di una certa precisione nella notifica, questa non è la strada da percorrere.

Soluzione 2:simulazione della scadenza con zset

L'idea qui è di non fare affidamento sul meccanismo di scadenza della chiave Redis, ma di simularlo utilizzando un indice aggiuntivo più un demone di polling. Può funzionare con una versione Redis 2.6 non modificata.

Ogni volta che una sessione viene aggiunta a Redis, puoi eseguire:

MULTI
SET <session id> <session content>
ZADD to_be_expired <current timestamp + session timeout> <session id>
EXEC

Il set ordinato to_be_expired è solo un modo efficiente per accedere alle prime chiavi che dovrebbero essere scadute. Un demone può eseguire il polling su to_be_expired utilizzando il seguente script Lua lato server:

local res = redis.call('ZRANGEBYSCORE',KEYS[1], 0, ARGV[1], 'LIMIT', 0, 10 )
if #res > 0 then
   redis.call( 'ZREMRANGEBYRANK', KEYS[1], 0, #res-1 )
   return res
else
   return false
end

Il comando per avviare lo script sarebbe:

EVAL <script> 1 to_be_expired <current timestamp>

Il demone riceverà al massimo 10 oggetti. Per ciascuno di essi, deve utilizzare il comando DEL per rimuovere le sessioni e notificare l'applicazione. Se un elemento è stato effettivamente elaborato (cioè il ritorno dello script Lua non è vuoto), il demone dovrebbe eseguire il loop immediatamente, altrimenti può essere introdotto uno stato di attesa di 1 secondo.

Grazie allo script Lua è possibile lanciare più demoni di polling in parallelo (lo script garantisce che una determinata sessione verrà elaborata una sola volta, poiché le chiavi vengono rimosse da to_be_expired dallo script Lua stesso).

Soluzione 3:utilizza un timer distribuito esterno

Un'altra soluzione è affidarsi a un timer distribuito esterno. Il sistema di accodamento leggero Beanstalk è una buona possibilità per questo

Ogni volta che una sessione viene aggiunta al sistema, l'applicazione invia l'ID sessione a una coda di beanstalk con un ritardo corrispondente al timeout della sessione. Un demone sta ascoltando la coda. Quando può rimuovere un elemento dalla coda, significa che una sessione è scaduta. Deve solo pulire la sessione in Redis e notificare l'applicazione.