La sorpresa (nessun evento di scadenza visto quando il tempo di vita per una chiave raggiunge lo zero) non è legato a Python, ma piuttosto al modo in cui Redis sta scadendo le chiavi.
Redis doc sulla tempistica degli eventi scaduti
Cronologia degli eventi scaduti
Le chiavi con un tempo di vita associato sono scadute da Redis in due modi:
- Quando si accede alla chiave da un comando e risulta scaduta.
- Tramite un sistema in background che ricerca in background le chiavi scadute, in modo incrementale, per poter raccogliere anche le chiavi a cui non si accede mai.
Gli eventi scaduti vengono generati quando si accede a una chiave e risulta scaduta da uno dei sistemi sopra indicati, di conseguenza non ci sono garanzie che il server Redis sarà in grado di generare l'evento scaduto nel momento in cui la chiave deve vivere raggiunge il valore zero.
Se nessun comando punta costantemente alla chiave e ci sono molte chiavi con un TTL associato, può esserci un ritardo significativo tra il momento in cui il tempo di permanenza della chiave scende a zero e il momento in cui viene generato l'evento scaduto.
Gli eventi sostanzialmente scaduti vengono generati quando il server Redis elimina la chiave e non quando il tempo da vivere raggiunge teoricamente il valore zero.
Piccolo test su console
quando Redis è in esecuzione ($ sudo service redis-server start
)
Ho avviato una console e mi sono iscritto:
$ redis-cli
PSUBSCRIBE "__key*__:*"
Quindi, in un'altra console:
$ redis-cli
> config set notify-keyspace-events AKE
cosa deve iscriversi a tutti i tipi di eventi
Poi ho continuato con gli esperimenti in questa seconda console:
> set aaa aaa
> del aaa
> set aaa ex 5
> get aaa
Tutte le attività sono state visualizzate nella console in abbonamento. Solo la scadenza della chiave è stata ritardata di alcuni secondi, a volte è arrivata appena in tempo.
Nota anche che ci sono sottili differenze nei messaggi, un messaggio [email protected]__:expire
un altro [email protected]__:expired
.
Ascoltatore di esempio spy.py
import redis
import time
r = redis.StrictRedis()
pubsub = r.pubsub()
pubsub.psubscribe("*")
for msg in pubsub.listen():
print time.time(), msg
Questo codice si registra su tutti i canali esistenti in modalità redis predefinita e stampa tutto ciò che viene pubblicato.
Eseguilo:
$ python spy.py
e in un'altra console prova a impostare una chiave con una scadenza. Vedrai tutti gli eventi.
Per il seguente input 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
otteniamo un output spia:
1401548400.27 {'pattern': None, 'type': 'psubscribe', 'channel': '*', 'data': 1L}
1401548428.36 {'pattern': '*', 'type': 'pmessage', 'channel': '[email protected]__:a', 'data': 'set'}
1401548428.36 {'pattern': '*', 'type': 'pmessage', 'channel': '[email protected]__:set', 'data': 'a'}
1401548436.8 {'pattern': '*', 'type': 'pmessage', 'channel': '[email protected]__:b', 'data': 'set'}
1401548436.8 {'pattern': '*', 'type': 'pmessage', 'channel': '[email protected]__:set', 'data': 'b'}
1401548436.8 {'pattern': '*', 'type': 'pmessage', 'channel': '[email protected]__:b', 'data': 'expire'}
1401548436.8 {'pattern': '*', 'type': 'pmessage', 'channel': '[email protected]__:expire', 'data': 'b'}
1401548439.82 {'pattern': '*', 'type': 'pmessage', 'channel': '[email protected]__:b', 'data': 'expired'}
1401548439.82 {'pattern': '*', 'type': 'pmessage', 'channel': '[email protected]__:expired', 'data': 'b'}
1401548484.46 {'pattern': '*', 'type': 'pmessage', 'channel': '[email protected]__:b', 'data': 'set'}
1401548484.46 {'pattern': '*', 'type': 'pmessage', 'channel': '[email protected]__:set', 'data': 'b'}
1401548484.46 {'pattern': '*', 'type': 'pmessage', 'channel': '[email protected]__:b', 'data': 'expire'}
1401548484.46 {'pattern': '*', 'type': 'pmessage', 'channel': '[email protected]__:expire', 'data': 'b'}
1401548487.51 {'pattern': '*', 'type': 'pmessage', 'channel': '[email protected]__:b', 'data': 'expired'}
1401548487.51 {'pattern': '*', 'type': 'pmessage', 'channel': '[email protected]__:expired', 'data': 'b'}