python - pubsub - redis query
Notificación de caducidad de clave en redis python (1)
Me gustaría recibir una notificación cuando una clave volátil caduque en mi tienda redis. El sitio web de redis proporciona una descripción de cómo se podría lograr esto en http://redis.io/topics/notifications , pero me pregunto si se puede hacer usando la red pyi api de python.
Después de configurar: notify-keyspace-events Ex
en mi archivo redis.conf
y ejecutando esto como una prueba:
import redis
import config
client = redis.StrictRedis.from_url(config.REDIS_URI)
client.set_response_callback(''EXPIRE'',callback)
client.set(''a'', 1)
client.expire(''a'',5)
callback()
solo recibe una llamada cuando se llama a client.expire(''a'',5)
, pero no cinco segundos después como se esperaba
La sorpresa (no se ven eventos de caducidad cuando el tiempo de vida de una clave llega a cero) no está vinculada a Python, sino que, por el contrario, Redis está expirando.
http://redis.io/topics/notifications
Tiempo de eventos vencidos
Redis caduca las claves con un tiempo de vida asociado de dos maneras:
- Cuando se accede a la clave mediante un comando y se encuentra caducada.
- A través de un sistema en segundo plano que busca claves caducadas en segundo plano, de forma incremental, para poder recopilar también claves a las que nunca se ha accedido.
Los eventos caducados se generan cuando se accede a una clave y uno de los sistemas anteriores determina que caducó, por lo que no hay garantías de que el servidor Redis pueda generar el evento caducado en el momento en que la clave esté activa. alcanza el valor de cero.
Si ningún comando apunta a la clave constantemente, y hay muchas claves con un TTL asociado, puede haber un retraso significativo entre el momento en que el tiempo de activación de la clave se pone en cero y el momento en que se genera el evento caducado.
Básicamente, los eventos caducados se generan cuando el servidor Redis elimina la clave y no cuando el tiempo de vida teóricamente alcanza el valor de cero.
Pequeño test en consola
cuando se ejecuta Redis ( $ sudo service redis-server start
)
Comencé una consola y me he suscrito:
$ redis-cli
PSUBSCRIBE "__key*__:*"
Luego, en otra consola:
$ redis-cli
> config set notify-keyspace-events AKE
Lo que se suscribirá a todo tipo de eventos.
Luego continué con experimentos en esta segunda consola:
> set aaa aaa
> del aaa
> set aaa ex 5
> get aaa
Todas las actividades fueron vistas en la consola suscrita. Solo la caducidad de la clave se retrasó unos segundos, en algún momento llegó justo a tiempo.
Tenga en cuenta que, además, hay diferencias sutiles en los mensajes, un mensaje __keyevent@0__:expire
otro __keyevent@0__:expired
.
spy.py
muestra spy.py
import redis
import time
r = redis.StrictRedis()
pubsub = r.pubsub()
pubsub.psubscribe("*")
for msg in pubsub.listen():
print time.time(), msg
Este código se registra en todos los canales existentes en redis por defecto e imprime lo que se publica.
Ejecutarlo:
$ python spy.py
y en otra consola intente configurar una clave con un vencimiento. Verás todos los eventos.
Para la siguiente entrada de redis-cli.
$ redis-cli
127.0.0.1:6379> set a aha
OK
127.0.0.1:6379> set b bebe ex 3
OK
127.0.0.1:6379> set b bebe ex 3
OK
obtenemos salida de espía:
1401548400.27 {''pattern'': None, ''type'': ''psubscribe'', ''channel'': ''*'', ''data'': 1L}
1401548428.36 {''pattern'': ''*'', ''type'': ''pmessage'', ''channel'': ''__keyspace@0__:a'', ''data'': ''set''}
1401548428.36 {''pattern'': ''*'', ''type'': ''pmessage'', ''channel'': ''__keyevent@0__:set'', ''data'': ''a''}
1401548436.8 {''pattern'': ''*'', ''type'': ''pmessage'', ''channel'': ''__keyspace@0__:b'', ''data'': ''set''}
1401548436.8 {''pattern'': ''*'', ''type'': ''pmessage'', ''channel'': ''__keyevent@0__:set'', ''data'': ''b''}
1401548436.8 {''pattern'': ''*'', ''type'': ''pmessage'', ''channel'': ''__keyspace@0__:b'', ''data'': ''expire''}
1401548436.8 {''pattern'': ''*'', ''type'': ''pmessage'', ''channel'': ''__keyevent@0__:expire'', ''data'': ''b''}
1401548439.82 {''pattern'': ''*'', ''type'': ''pmessage'', ''channel'': ''__keyspace@0__:b'', ''data'': ''expired''}
1401548439.82 {''pattern'': ''*'', ''type'': ''pmessage'', ''channel'': ''__keyevent@0__:expired'', ''data'': ''b''}
1401548484.46 {''pattern'': ''*'', ''type'': ''pmessage'', ''channel'': ''__keyspace@0__:b'', ''data'': ''set''}
1401548484.46 {''pattern'': ''*'', ''type'': ''pmessage'', ''channel'': ''__keyevent@0__:set'', ''data'': ''b''}
1401548484.46 {''pattern'': ''*'', ''type'': ''pmessage'', ''channel'': ''__keyspace@0__:b'', ''data'': ''expire''}
1401548484.46 {''pattern'': ''*'', ''type'': ''pmessage'', ''channel'': ''__keyevent@0__:expire'', ''data'': ''b''}
1401548487.51 {''pattern'': ''*'', ''type'': ''pmessage'', ''channel'': ''__keyspace@0__:b'', ''data'': ''expired''}
1401548487.51 {''pattern'': ''*'', ''type'': ''pmessage'', ''channel'': ''__keyevent@0__:expired'', ''data'': ''b''}