sql >> Base de Datos >  >> NoSQL >> Redis

¿Cómo manejar la caducidad de la sesión basada en redis?

Por lo tanto, necesita que su aplicación reciba una notificación cuando una sesión expire en Redis.

Si bien Redis no es compatible con esta función, hay una serie de trucos que puede usar para implementarla.

Actualización:a partir de la versión 2.8.0, Redis admite esta http://redis.io/topics/notifications

Primero, la gente está pensando en ello:todavía se está debatiendo, pero podría agregarse a una versión futura de Redis. Consulte los siguientes problemas:

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

Ahora, aquí hay algunas soluciones que puede usar con las versiones actuales de Redis.

Solución 1:parchear Redis

En realidad, agregar una notificación simple cuando Redis realiza la caducidad de la clave no es tan difícil. Se puede implementar agregando 10 líneas al archivo db.c del código fuente de Redis. Aquí hay un ejemplo:

https://gist.github.com/3258233

Este breve parche publica una clave en la lista #caducada si la clave ha caducado y comienza con un carácter '@' (opción arbitraria). Se puede adaptar fácilmente a tus necesidades.

Entonces es trivial usar los comandos EXPIRE o SETEX para establecer un tiempo de vencimiento para sus objetos de sesión y escribir un pequeño demonio que se repite en BRPOP para salir de la cola de la lista "#expired" y propagar la notificación en su aplicación.

Un punto importante es comprender cómo funciona el mecanismo de caducidad en Redis. En realidad, hay dos rutas diferentes para la caducidad, ambas activas al mismo tiempo:

  • Mecanismo perezoso (pasivo). La caducidad puede ocurrir cada vez que se accede a una clave.

  • Mecanismo activo. Un trabajo interno muestra regularmente (aleatoriamente) una cantidad de claves con vencimiento establecido, tratando de encontrar las que caducan.

Tenga en cuenta que el parche anterior funciona bien con ambas rutas.

La consecuencia es que el tiempo de expiración de Redis no es exacto. Si todas las claves caducan, pero solo una está a punto de caducar y no se accede a ella, el trabajo de caducidad activo puede tardar varios minutos en encontrar la clave y caducarla. Si necesita algo de precisión en la notificación, este no es el camino a seguir.

Solución 2:simular caducidad con zsets

La idea aquí es no confiar en el mecanismo de caducidad de clave de Redis, sino simularlo mediante el uso de un índice adicional más un demonio de sondeo. Puede funcionar con una versión Redis 2.6 sin modificar.

Cada vez que se agrega una sesión a Redis, puede ejecutar:

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

El conjunto ordenado to_be_expired es solo una forma eficiente de acceder a las primeras claves que deben caducar. Un demonio puede sondear to_be_expired utilizando el siguiente script del lado del servidor 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

El comando para ejecutar el script sería:

EVAL <script> 1 to_be_expired <current timestamp>

El daemon obtendrá como máximo 10 artículos. Para cada uno de ellos, debe usar el comando DEL para eliminar las sesiones y notificar a la aplicación. Si un elemento se procesó realmente (es decir, el retorno del script Lua no está vacío), el daemon debe repetirse inmediatamente; de ​​lo contrario, se puede introducir un estado de espera de 1 segundo.

Gracias al script de Lua, es posible lanzar varios demonios de sondeo en paralelo (el script garantiza que una sesión determinada solo se procesará una vez, ya que el propio script de Lua elimina las claves de to_be_expired).

Solución 3:use un temporizador distribuido externo

Otra solución es confiar en un temporizador distribuido externo. El sistema de colas ligero beanstalk es una buena posibilidad para esto

Cada vez que se agrega una sesión en el sistema, la aplicación publica el ID de la sesión en una cola de beanstalk con un retraso correspondiente al tiempo de espera de la sesión. Un demonio está escuchando la cola. Cuando puede sacar de la cola un elemento, significa que una sesión ha expirado. Solo tiene que limpiar la sesión en Redis y notificar a la aplicación.