De verrassing (er worden geen expiratiegebeurtenissen gezien wanneer de tijd om te leven voor een sleutel nul bereikt) is niet gebonden aan Python, maar eerder aan de manier waarop Redis de sleutels laat verlopen.
Redis-document over timing van verlopen evenementen
Timing van verlopen evenementen
Sleutels waaraan een tijd om te leven is gekoppeld, worden op twee manieren door Redis verlopen:
- Als de sleutel wordt benaderd door een commando en blijkt te zijn verlopen.
- Via een achtergrondsysteem dat incrementeel op de achtergrond naar verlopen sleutels zoekt om ook sleutels te kunnen verzamelen die nooit worden gebruikt.
De verlopen gebeurtenissen worden gegenereerd wanneer een sleutel wordt geopend en blijkt te zijn verlopen door een van de bovenstaande systemen, met als gevolg dat er geen garanties zijn dat de Redis-server de verlopen gebeurtenis kan genereren op het moment dat de sleutel actief is bereikt de waarde nul.
Als er geen commando constant op de sleutel is gericht, en er zijn veel sleutels met een TTL geassocieerd, kan er een aanzienlijke vertraging zijn tussen het moment dat de sleuteltijd tot nul daalt en het moment waarop de verlopen gebeurtenis wordt gegenereerd.
In principe verlopen gebeurtenissen worden gegenereerd wanneer de Redis-server de sleutel verwijdert en niet wanneer de tijd om te leven theoretisch de waarde nul bereikt.
Kleine test op console
wanneer Redis wordt uitgevoerd ($ sudo service redis-server start
)
Ik ben met één console begonnen en heb me geabonneerd:
$ redis-cli
PSUBSCRIBE "__key*__:*"
Dan, in een andere console:
$ redis-cli
> config set notify-keyspace-events AKE
wat zal zich abonneren op allerlei evenementen
Daarna ging ik verder met experimenten in deze tweede console:
> set aaa aaa
> del aaa
> set aaa ex 5
> get aaa
Alle activiteiten waren te zien in de geabonneerde console. Alleen het verlopen van de sleutel was soms een paar seconden vertraagd, soms kwam het net op tijd.
Merk ook op dat er subtiele verschillen zijn in berichten, één bericht [email protected]__:expire
een ander [email protected]__:expired
.
Voorbeeld luisteraar spy.py
import redis
import time
r = redis.StrictRedis()
pubsub = r.pubsub()
pubsub.psubscribe("*")
for msg in pubsub.listen():
print time.time(), msg
Deze code wordt standaard opnieuw geregistreerd bij alle bestaande kanalen en drukt af wat wordt gepubliceerd.
Voer het uit:
$ python spy.py
en probeer in een andere console een sleutel in te stellen met een vervaldatum. Je ziet alle evenementen.
Voor volgende redis-cli-invoer.
$ 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
we krijgen spionage-output:
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'}