简体   繁体   English

redis python中密钥到期的通知

[英]Notification of key expiration in redis python

I would like to be notified when a volatile key expires in my redis store. 我希望在我的redis商店中挥发性密钥到期时收到通知。 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. redis网站提供了一些关于如何在http://redis.io/topics/notifications中实现这一目标的描述,但我想知道是否可以使用python redis api完成。

After setting: notify-keyspace-events Ex in my redis.conf file 在我的redis.conf文件中设置: notify-keyspace-events Ex之后

and running this as a test: 并将其作为测试运行:

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() only gets called when client.expire('a',5) gets called, but not five seconds later as expected callback()仅在调用client.expire('a',5)时调用,但不会在五秒后调用

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. 令人惊讶的是(当密钥的生存时间达到零时没有看到过期事件)不受Python限制,而是Redis过期密钥的方式。

Redis doc on Timing of expired events Redis doc关于过期事件的时间安排

Timing of expired events 过期事件的时间安排

Keys with a time to live associated are expired by Redis in two ways: 具有生存时间关联的密钥由Redis以两种方式过期:

  • When the key is accessed by a command and is found to be expired. 当命令访问密钥并发现它已过期时。
  • Via a background system that looks for expired keys in background, incrementally, in order to be able to also collect keys that are never accessed. 通过后台系统,在后台逐步查找过期的密钥,以便能够收集从未访问过的密钥。

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. 当访问密钥并且发现上述系统之一过期时,会生成过期事件,因此无法保证Redis服务器能够在关键时间生成过期事件达到零值。

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. 如果没有命令持续定位密钥,并且有许多密钥与TTL相关联,则密钥生存时间降至零的时间与生成过期事件的时间之间可能存在显着延迟。

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服务器删除密钥时生成基本过期的事件而不是在理论上生存时间达到零值时生成。

Small test on console 在控制台上进行小测试

when Redis running ( $ sudo service redis-server start ) 当Redis运行时( $ 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

what shall subscribe to all kinds of events 什么应该订阅各种事件

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. 只有关键的到期时间延迟了几秒钟,有时恰好是时候了。

Note alse, there are subtle differences in messages, one message __keyevent@0__:expire another __keyevent@0__:expired . 另请注意,消息中存在细微差别,一条消息__keyevent@0__:expire另一条__keyevent@0__:expired

Sample listener spy.py 示例监听器spy.py

import redis
import time

r = redis.StrictRedis()
pubsub = r.pubsub()
pubsub.psubscribe("*")
for msg in pubsub.listen():
    print time.time(), msg

This code registers to all existing channels in default redis and prints whatever gets published. 此代码在默认redis中注册到所有现有通道,并打印任何已发布的内容。

Run it: 运行:

$ python spy.py

and in another console try to set a key with an expiration. 并在另一个控制台中尝试设置一个到期的密钥。 You will see all the events. 你会看到所有的事件。

For following redis-cli 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

we get spy output: 我们得到间谍输出:

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'}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM