Musisz więc, aby Twoja aplikacja była powiadamiana o wygaśnięciu sesji w Redis.
Chociaż Redis nie obsługuje tej funkcji, istnieje wiele sztuczek, których możesz użyć, aby ją zaimplementować.
Aktualizacja:od wersji 2.8.0 Redis obsługuje to http://redis.io/topics/notifications
Po pierwsze, ludzie o tym myślą:jest to nadal przedmiotem dyskusji, ale może zostać dodane do przyszłej wersji Redis. Zobacz następujące problemy:
- https://github.com/antirez/redis/issues/83
- https://github.com/antirez/redis/issues/594
Oto kilka rozwiązań, których możesz użyć w obecnych wersjach Redis.
Rozwiązanie 1:łatanie Redisa
W rzeczywistości dodanie prostego powiadomienia, gdy Redis przeprowadza wygaśnięcie klucza, nie jest takie trudne. Można to zaimplementować poprzez dodanie 10 linii do pliku db.c kodu źródłowego Redis. Oto przykład:
https://gist.github.com/3258233
Ta krótka łatka umieszcza klucz na liście #expired, jeśli klucz wygasł i zaczyna się od znaku „@” (wybór arbitralny). Można go łatwo dostosować do własnych potrzeb.
Wtedy trywialne jest użycie poleceń EXPIRE lub SETEX, aby ustawić czas wygaśnięcia obiektów sesji i napisać małego demona, który zapętla się na BRPOP, aby usunąć kolejkę z listy „#expired” i rozpropagować powiadomienie w aplikacji.
Ważnym punktem jest zrozumienie, jak działa mechanizm wygaśnięcia w Redis. W rzeczywistości istnieją dwie różne ścieżki wygaśnięcia, obie aktywne w tym samym czasie:
-
Mechanizm leniwy (pasywny). Wygaśnięcie może nastąpić przy każdym dostępie do klucza.
-
Mechanizm aktywny. Zadanie wewnętrzne regularnie (losowo) pobiera próbki kluczy z ustawionym terminem ważności, próbując znaleźć te, które wygasają.
Zauważ, że powyższa łatka działa dobrze z obiema ścieżkami.
Konsekwencją jest to, że czas wygaśnięcia Redis nie jest dokładny. Jeśli wszystkie klucze wygasły, ale tylko jeden jest bliski wygaśnięcia i nie ma do niego dostępu, aktywne zadanie wygasania może potrwać kilka minut, aby znaleźć klucz i utracić ważność. Jeśli potrzebujesz dokładności w powiadomieniu, to nie jest droga.
Rozwiązanie 2:symulacja wygaśnięcia za pomocą zsets
Pomysł polega na tym, aby nie polegać na mechanizmie wygasania klucza Redis, ale zasymulować go za pomocą dodatkowego indeksu i demona odpytującego. Może działać z niezmodyfikowaną wersją Redis 2.6.
Za każdym razem, gdy sesja jest dodawana do Redis, możesz uruchomić:
MULTI
SET <session id> <session content>
ZADD to_be_expired <current timestamp + session timeout> <session id>
EXEC
Posortowany zestaw to_be_expired jest po prostu skutecznym sposobem uzyskania dostępu do pierwszych kluczy, które powinny wygasnąć. Demon może odpytywać to_be_expired za pomocą następującego skryptu po stronie serwera Lua:
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
Polecenie uruchomienia skryptu to:
EVAL <script> 1 to_be_expired <current timestamp>
Demon dostanie maksymalnie 10 przedmiotów. Dla każdego z nich musi użyć polecenia DEL, aby usunąć sesje i powiadomić aplikację. Jeśli jeden element został faktycznie przetworzony (tzn. powrót skryptu Lua nie jest pusty), demon powinien natychmiast zapętlić się, w przeciwnym razie można wprowadzić stan oczekiwania na 1 sekundę.
Dzięki skryptowi Lua możliwe jest równoległe uruchomienie kilku demonów odpytujących (skrypt gwarantuje, że dana sesja zostanie przetworzona tylko raz, ponieważ klucze są usuwane z to_be_expired przez sam skrypt Lua).
Rozwiązanie 3:użyj zewnętrznego rozproszonego timera
Innym rozwiązaniem jest poleganie na zewnętrznym rozproszonym zegarze. Lekki system kolejkowania fasoli jest do tego dobrą możliwością
Za każdym razem, gdy w systemie dodawana jest sesja, aplikacja wysyła identyfikator sesji do kolejki beanstalk z opóźnieniem odpowiadającym wygaśnięciu sesji. Demon nasłuchuje kolejki. Kiedy może usunąć element z kolejki, oznacza to, że sesja wygasła. Wystarczy wyczyścić sesję w Redis i powiadomić aplikację.