Redis 2.8通知:获取值而不是密钥(在过期时)

时间:2013-08-20 06:09:14

标签: database events redis

我们有以下用例:每当某个密钥到期时,我们都需要根据它的价值得到通知并做一些事情。但是当redis触发expired事件时,当我们稍后尝试访问它时,密钥已经从数据库中删除了,这当然是预期的。

现在有没有办法在它过期后再次访问该条目?我猜不是。

所以第二个选项:有没有办法告诉redis在发送这些事件时发布整个值对象而不仅仅是密钥?我想它可以通过Lua添加,但如果可能的话,我会对更简单的选项感兴趣。我们还需要针对其他事件的此行为,我们基本上需要所有通知来发布值,而不是密钥(我们可以在收到事件后执行GET,但我们希望绕过第二次调用,主要是有一个原子进程,因为在发布事件和执行GET以检索值之间值可能已经改变。)

希望这是可以理解的。也许我们看不到明显的,所以提前谢谢!

3 个答案:

答案 0 :(得分:33)

Eli链接的功能允许您在密钥到期时进行监听。但是,它不会为您提供密钥的值。此外,根据提交的github问题,看起来你似乎不希望在任何时候很快建立这个功能(https://github.com/antirez/redis/issues/1876)。我使用的解决方案是创建一个特殊的“影子”过期密钥,该密钥链接到您具有实际值的密钥。

因此,假设您有一个名为testkey的密钥,它的整数值为100。此外,密钥将在10秒后到期,此时您希望获得密钥的值。 (也许你在它存在的10秒内递增了密钥)。

首先,您需要设置侦听键空间事件。特别是你想听expired个事件。您可以从配置中执行此操作,也可以在redis中使用config set命令。 (详情请见http://redis.io/topics/notifications

CONFIG SET notify-keyspace-events Ex

现在,您可以订阅一个特殊的keyevent频道,通知您该密钥已过期。

SUBSCRIBE __keyevent@0__:expired

订阅频道的格式为__keyevent@<db>__:<eventName>。在我们的示例中,我们假设我们正在使用默认数据库0,并且我们想要监听expired事件。

testkey过期后,您将在__keyevent__频道收到一条消息,其中消息是过期密钥的名称。当然,此时密钥已经消失,因此我们无法再访问该值!解决方案是使用特殊的过期密钥。

创建testkey时,还要创建一个特殊的过期“阴影”键(不要使实际的testkey失效)。例如:

SET testkey 100
SET shadowkey:testkey "" EX 10

现在,在__keyevent@0__:expired频道中,您会收到一条消息,告知您密钥shadowkey:testkey已过期。获取消息的值(键的名称),在冒号(或您决定使用的任何分隔符)上拆分,然后手动获取键的值并将其删除。

// set your key value
SET testkey 100 
//set your "shadow" key, note the value here is irrelevant
SET shadowkey:testkey "" EX 10 
// Get an expiration message in the channel __keyevent@0__:expired
// Split the key on ":", take the second part to get your original key
// Then get the value and do whatever with it
GET testkey
// Then delete the key
DEL testkey

请注意,不使用shadowkey的值,因此您希望使用根据此答案(Redis store key without a value)为空字符串""的最小可能值。设置工作要多一些,但上述系统完全符合您的需求。开销是一些额外的命令,用于实际检索和删除密钥以及空密钥的存储成本。

答案 1 :(得分:1)

如果您使用的是2.8,则可以试用this new feature(也在this page引用)。它肯定是不稳定的,似乎没有经过充分测试,但如果你还是2.8,那么......

问题页面的简介:

  

具有键值数据模型的数据库中的一个有趣功能(Redis   由于值是复杂数据,因此不完全符合此定义   结构,但Redis的外层绝对是一个关键值   business)是以某种方式订阅流的能力   针对特定密钥的事件。

     

例如,我可能有兴趣看看密钥foo何时被删除或   以某种方式修改,或获取所有键的名称   expis set(使用EXPIRE命令),Redis正在从中驱逐出去   数据集,因为它们的生存时间降至零。

     

然而,Redis用户群多次请求此功能   到目前为止,我们从未达到过提议的API(包括   我自己提出的建议似乎很适合Redis的设计。   此功能请求将尝试描述新设计   非常简单易用,实现,并且非常适合Redis   故事。

答案 2 :(得分:0)

我建议您将所需的相关值作为密钥的一部分。 例如,如果您的值是一个属性很少的对象(如userId,date等) 如果足以让您知道过期的userId, 因此,您可以创建这样的密钥: someGuid_userId 然后在过期时将其提取到事件处理程序中