26

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

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

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

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

4

2 回答 2

55

Eli 链接到的功能允许您在密钥过期时进行监听。但是,它不会为您提供密钥的值。此外,根据提交的 github 问题,如果有的话,您似乎无法期望在任何时候都内置此功能。我使用的解决方案是创建一个特殊的“影子”到期密钥,该密钥链接到您拥有实际值的密钥。

因此,假设您有一个名为的键testkey,它的整数值为100. 此外,密钥将在 10 秒后过期,此时您想要获取密钥的值。(也许您在密钥存在的 10 秒内递增密钥)。

首先,您需要设置监听键空间事件。特别是你想监听expired事件。您可以从配置中执行此操作,也可以config set在 redis 中使用该命令。(有关更多信息,请参见此处: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)的最小可能值是一个空字符串""。设置需要做更多的工作,但上述系统完全可以满足您的需要。开销是一些额外的命令来实际检索和删除您的密钥以及空密钥的存储成本。

于 2015-02-21T15:58:48.793 回答
1

如果您使用的是 2.8,则可以试用此新功能(也在此页面中引用)。它绝对不稳定,似乎没有经过很好的测试,但如果你在 2.8 上...

问题页面的简短介绍:

具有键值数据模型的数据库中一个有趣的特性(Redis 并不完全符合这个定义,因为值是复杂的数据结构,但 Redis 的外层绝对是键值业务)是以某种方式订阅的能力到针对给定键的事件流。

例如,我可能有兴趣查看密钥 foo 何时以某种方式被删除或修改,或者获取 Redis 从数据集中逐出的所有具有过期集的密钥的名称(使用 EXPIRE 命令),因为它们的时间直播降为零。

Redis 用户群多次要求此功能,但到目前为止,我们从未达到提议的 API(包括我自己提出的提议)似乎很好地融入 Redis 设计的地步。此功能请求将尝试描述一种新设计,该设计非常易于使用和实现,并且非常适合 Redis 的故事。

于 2013-08-20T20:32:11.917 回答