我们有以下用例:每当某个密钥到期时,我们都需要根据它的价值得到通知并做一些事情。但是当redis触发expired
事件时,当我们稍后尝试访问它时,密钥已经从数据库中删除了,这当然是预期的。
现在有没有办法在它过期后再次访问该条目?我猜不是。
所以第二个选项:有没有办法告诉redis在发送这些事件时发布整个值对象而不仅仅是密钥?我想它可以通过Lua添加,但如果可能的话,我会对更简单的选项感兴趣。我们还需要针对其他事件的此行为,我们基本上需要所有通知来发布值,而不是密钥(我们可以在收到事件后执行GET
,但我们希望绕过第二次调用,主要是有一个原子进程,因为在发布事件和执行GET
以检索值之间值可能已经改变。)
希望这是可以理解的。也许我们看不到明显的,所以提前谢谢!
答案 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 然后在过期时将其提取到事件处理程序中