问题描述
我希望在我的 redis 存储中的易失性密钥过期时收到通知.redis 网站提供了一些关于如何在 http://redis.io/topics/notifications 中实现这一点的描述,但我是想知道是否可以使用 python redis api 来完成.
I would like to be notified when a volatile key expires in my redis store. The redis website provides some description of how this might be achieved in http://redis.io/topics/notifications, but I am wondering if it can be done using the python redis api.
设置后:notify-keyspace-events Ex
在我的 redis.conf 文件中
After setting:notify-keyspace-events Ex
in my redis.conf file
并将其作为测试运行:
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()
仅在 client.expire('a',5)
被调用时被调用,但不会像预期的那样在五秒后
callback()
only gets called when client.expire('a',5)
gets called, but not five seconds later as expected
推荐答案
惊喜(当键的生存时间达到零时没有看到过期事件)与 Python 无关,而是与方式有关,Redis 正在使键过期.
The surprise (no expiration events seen when time to live for a key reaches zero) is not bound to Python, but rather to the way, Redis is expiring keys.
具有生存时间关联的键通过两种方式被 Redis 过期:
Keys with a time to live associated are expired by Redis in two ways:
- 当通过命令访问密钥并发现密钥已过期时.
- 通过后台系统逐步查找过期密钥,以便能够收集从未访问过的密钥.
过期事件是在访问某个键并被上述系统之一发现过期时生成的,因此无法保证Redis服务器能够在该键时生成过期事件生存时间达到零值.
The expired events are generated when a key is accessed and is found to be expired by one of the above systems, as a result there are no guarantees that the Redis server will be able to generate the expired event at the time the key time to live reaches the value of zero.
如果没有命令始终针对密钥,并且有许多密钥与 TTL 相关联,则密钥的生存时间降至零与生成过期事件的时间之间可能存在显着延迟.
If no command targets the key constantly, and there are many keys with a TTL associated, there can be a significant delay between the time the key time to live drops to zero, and the time the expired event is generated.
基本上过期事件在Redis服务器删除key时产生,而不是在理论上存活时间达到零值时产生.
Basically expired events are generated when the Redis server deletes the key and not when the time to live theoretically reaches the value of zero.
Redis 运行时($ sudo service redis-server start
)
when Redis running ($ sudo service redis-server start
)
我启动了一个控制台并订阅了:
I started one console and have subscribed:
$ redis-cli
PSUBSCRIBE "__key*__:*"
然后,在另一个控制台中:
Then, in another console:
$ redis-cli
> config set notify-keyspace-events AKE
什么应该订阅各种事件
然后我继续在第二个控制台中进行实验:
Then I continued with experiments in this second console:
> set aaa aaa
> del aaa
> set aaa ex 5
> get aaa
所有活动都在订阅的控制台中看到.只有密钥过期有时延迟了几秒钟,有时来得正好.
All the activities were seen in subscribed console. Only the key expiration was sometime few seconds delayed, sometime came just in time.
另外请注意,消息之间存在细微差别,一条消息 __keyevent@0__:expire
另一条消息 __keyevent@0__:expired
.
Note alse, there are subtle differences in messages, one message __keyevent@0__:expire
another __keyevent@0__:expired
.
import redis
import time
r = redis.StrictRedis()
pubsub = r.pubsub()
pubsub.psubscribe("*")
for msg in pubsub.listen():
print time.time(), msg
此代码注册到默认 redis 中的所有现有频道并打印发布的任何内容.
This code registers to all existing channels in default redis and prints whatever gets published.
运行它:
$ python spy.py
并在另一个控制台中尝试设置一个过期的密钥.您将看到所有事件.
and in another console try to set a key with an expiration. You will see all the events.
用于以下 redis-cli 输入.
For following redis-cli input.
$ 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'}
这篇关于redis python中密钥过期的通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!