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

Dan*_*res 18 database events redis

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

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

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

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

Sar*_*rus 37

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

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

首先,您需要设置侦听键空间事件.特别是你想听expired事件.您可以从配置中执行此操作或使用config setredis中的命令.(有关详细信息,请参阅此处:http://redis.io/topics/notifications)

CONFIG SET notify-keyspace-events Ex
Run Code Online (Sandbox Code Playgroud)

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

SUBSCRIBE __keyevent@0__:expired
Run Code Online (Sandbox Code Playgroud)

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

testkey到期时,你现在会在收到一条消息,__keyevent__该消息是过期键的名称通道.当然,此时密钥已经消失,因此我们无法再访问该值!解决方案是使用特殊的过期密钥.

当你创建你testkey也创建一个特殊的到期"阴影"键(不要过期实际testkey).例如:

SET testkey 100
SET shadowkey:testkey "" EX 10
Run Code Online (Sandbox Code Playgroud)

现在,在__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
Run Code Online (Sandbox Code Playgroud)

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

  • 但有一个警告。如果您的客户端在获取事件或删除包含实际值的键之前中断,您最终将被过时的键污染您的 Redis。解决方案可能是将实际密钥设置为也过期,可能是在影子密钥之后 10 秒,这样您就有时间在影子密钥过期后获取它,然后忽略非影子密钥上的事件。 (2认同)