意外(当密钥的生存时间达到零时没有看到过期事件)与 Python 无关,而是与 Redis 使密钥过期的方式有关。
Redis doc on Timing of expired events
过期事件的时间
Redis 以两种方式使与生存时间相关联的密钥过期:
- 当密钥被命令访问并发现已过期时。
- 通过后台系统在后台逐步查找过期密钥,以便能够收集从未访问过的密钥。
expired events 是在 key 被访问并被上述系统之一发现过期时生成的,因此无法保证 Redis 服务器能够在 key 时生成 expired event生存时间达到零。
如果没有命令始终以键为目标,并且有许多键与 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
所有活动都在订阅的控制台中看到。只有密钥过期有时会延迟几秒钟,有时会及时到来。
另外请注意,消息存在细微差别,一条消息__keyevent@0__:expire另一条__keyevent@0__: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': '__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'}