Ответ 1
Неожиданность (без истечения срока действия, когда время жизни для ключа достигает нуля) не привязана к Python, а скорее к пути, у Redis есть ключи.
Документ Redis о сроках истекших событий
Сроки истечения срока действия
Ключи со временем для жизни связаны с Redis двумя способами:
- Когда ключ получает доступ к команде и, как установлено, истек.
- Через систему фона, которая ищет устаревшие ключи в фоновом режиме, постепенно, чтобы иметь возможность собирать ключи, которые никогда не доступны.
Истекшие события генерируются при доступе к ключу и истечения срока действия одной из вышеупомянутых систем, в результате чего нет гарантий, что сервер Redis сможет генерировать истекшее событие в момент нажатия клавиши время жизни достигает значения нуля.
Если никакая команда не нацеливает ключ постоянно, и есть много ключей с ассоциированным TTL, может быть значительная задержка между временем, в течение которого ключевое время жизни падает до нуля, и время, в течение которого генерируется истекшее событие.
События с истекшим сроком действия генерируются, когда сервер Redis удаляет ключ, а не когда время на проживание теоретически достигает значения нуля.
Малый тест на консоли
при запуске Redis ($ sudo service redis-server start
)
Я запустил одну консоль и подписался:
$ redis-cli
PSUBSCRIBE "__key*__:*"
Затем в другой консоли:
$ redis-cli
> config set notify-keyspace-events AKE
что подписаться на все виды событий
Затем я продолжил эксперименты на этой второй консоли:
> set aaa aaa
> del aaa
> set aaa ex 5
> get aaa
Все действия были видны в подписанной консоли. Только истечение срока действия ключа было несколько секунд задержано, когда-то как раз вовремя.
Заметьте alse, есть тонкие различия в сообщениях, одно сообщение [email protected]__:expire
другое [email protected]__:expired
.
Пример прослушивателя spy.py
import redis
import time
r = redis.StrictRedis()
pubsub = r.pubsub()
pubsub.psubscribe("*")
for msg in pubsub.listen():
print time.time(), msg
Этот код регистрирует все существующие каналы по умолчанию redis и печатает все, что публикуется.
Запустите его:
$ python spy.py
а в другой консоли попробуйте установить ключ с истечением срока действия. Вы увидите все события.
Для следующего входа 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
получаем шпионский вывод:
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'}