【问题标题】:Notification of key expiration in redis pythonredis python中的密钥过期通知
【发布时间】:2014-07-20 19:13:23
【问题描述】:

我希望在我的 redis 存储中的 volatile 密钥过期时收到通知。 redis 网站在http://redis.io/topics/notifications 中提供了一些关于如何实现这一点的描述,但我想知道是否可以使用 python redis api 来完成。

在我的redis.conf文件中设置:notify-keyspace-events Ex

并将其作为测试运行:

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) 被调用时才被调用,但不会像预期的那样晚五秒

【问题讨论】:

    标签: python python-2.7 redis


    【解决方案1】:

    意外(当密钥的生存时间达到零时没有看到过期事件)与 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'}
    

    【讨论】:

    • 他们的问题不是延迟,而是它从未发送过的事实。我能够使用 redis-cli 获得预期的结果,但我不清楚这些命令如何转换为 python API。谢谢
    • @samfr 示例显示如何订阅和监视添加的所有事件。
    猜你喜欢
    • 2020-04-19
    • 1970-01-01
    • 1970-01-01
    • 2011-02-22
    • 2020-09-26
    • 2016-04-25
    • 2012-08-04
    • 2017-09-18
    • 2023-03-04
    相关资源
    最近更新 更多