Je hebt dus nodig dat je applicatie een melding krijgt wanneer een sessie verloopt in Redis.
Hoewel Redis deze functie niet ondersteunt, zijn er een aantal trucs die u kunt gebruiken om deze te implementeren.
Update:vanaf versie 2.8.0 ondersteunt Redis dit http://redis.io/topics/notifications
Ten eerste denken mensen erover na:hier wordt nog over gediscussieerd, maar het kan worden toegevoegd aan een toekomstige versie van Redis. Zie de volgende problemen:
- https://github.com/antirez/redis/issues/83
- https://github.com/antirez/redis/issues/594
Hier zijn enkele oplossingen die u kunt gebruiken met de huidige Redis-versies.
Oplossing 1:Redis patchen
Eigenlijk is het niet zo moeilijk om een eenvoudige melding toe te voegen wanneer Redis de sleutel verloopt. Het kan worden geïmplementeerd door 10 regels toe te voegen aan het db.c-bestand van de Redis-broncode. Hier is een voorbeeld:
https://gist.github.com/3258233
Deze korte patch plaatst een sleutel in de #expired-lijst als de sleutel is verlopen en begint met een '@'-teken (willekeurige keuze). Het kan eenvoudig worden aangepast aan uw behoeften.
Het is dan triviaal om de EXPIRE- of SETEX-commando's te gebruiken om een vervaltijd in te stellen voor uw sessie-objecten, en een kleine daemon te schrijven die op BRPOP loopt om de wachtrij uit de "#expired"-lijst te verwijderen, en de melding in uw toepassing te verspreiden.
Een belangrijk punt is om te begrijpen hoe het expiratiemechanisme in Redis werkt. Er zijn eigenlijk twee verschillende paden voor de vervaldatum, beide tegelijkertijd actief:
-
Lui (passief) mechanisme. De vervaldatum kan elke keer dat een sleutel wordt gebruikt plaatsvinden.
-
Actief mechanisme. Een interne taak bemonstert regelmatig (willekeurig) een aantal sleutels waarvan de vervaldatum is ingesteld, in een poging de verlopen te vinden.
Merk op dat de bovenstaande patch goed werkt met beide paden.
Het gevolg is dat de vervaltijd van Redis niet nauwkeurig is. Als alle sleutels zijn verlopen, maar er slechts één op het punt staat te verlopen en er geen toegang tot is, kan het enkele minuten duren voordat de actieve vervaltaak de sleutel vindt en is verlopen. Als je nauwkeurigheid in de melding nodig hebt, is dit niet de juiste keuze.
Oplossing 2:vervaldatum simuleren met zsets
Het idee hier is om niet te vertrouwen op het Redis-sleutelvervalmechanisme, maar het te simuleren door een extra index plus een polling-daemon te gebruiken. Het kan werken met een ongewijzigde Redis 2.6-versie.
Elke keer dat een sessie aan Redis wordt toegevoegd, kunt u het volgende uitvoeren:
MULTI
SET <session id> <session content>
ZADD to_be_expired <current timestamp + session timeout> <session id>
EXEC
De to_be_expired gesorteerde set is slechts een efficiënte manier om toegang te krijgen tot de eerste sleutels die moeten zijn verlopen. Een daemon kan pollen op to_be_expired met behulp van het volgende Lua server-side script:
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
De opdracht om het script te starten zou zijn:
EVAL <script> 1 to_be_expired <current timestamp>
De daemon krijgt maximaal 10 items. Voor elk van hen moet het de opdracht DEL gebruiken om de sessies te verwijderen en de toepassing op de hoogte te stellen. Als een item daadwerkelijk is verwerkt (d.w.z. de terugkeer van het Lua-script is niet leeg), moet de daemon onmiddellijk worden herhaald, anders kan er een wachtstatus van 1 seconde worden geïntroduceerd.
Dankzij het Lua-script is het mogelijk om meerdere polling-daemons parallel te starten (het script garandeert dat een bepaalde sessie slechts één keer wordt verwerkt, aangezien de sleutels worden verwijderd van to_be_expired door het Lua-script zelf).
Oplossing 3:gebruik een externe gedistribueerde timer
Een andere oplossing is om te vertrouwen op een externe gedistribueerde timer. Het lichtgewicht rijsysteem van de bonenstaak is hiervoor een goede mogelijkheid
Elke keer dat een sessie aan het systeem wordt toegevoegd, plaatst de toepassing de sessie-ID in een Beanstalk-wachtrij met een vertraging die overeenkomt met de time-out van de sessie. Een daemon luistert naar de wachtrij. Wanneer het een item uit de wachtrij kan halen, betekent dit dat een sessie is verlopen. Het hoeft alleen de sessie in Redis op te schonen en de applicatie op de hoogte te stellen.