我有一个 Redis 服务器,其中包含一组键值对和一个排序集,提供这些键值对的键的索引。
键值对可以进入“已完成”状态,此时需要在 1 小时后删除它们。 这可以通过在键上设置过期时间来简单地实现,但从排序集中清除它们似乎会出现更多问题。
我可以有一个过程来扫描这些集合并不时更新它们,但如果有一些更干净的东西就更好了。
我认为没有办法在到期时触发诸如存储过程之类的内容或对排序的设置值设置到期时间。
我错过了什么,还是手动是唯一的方法?
最佳答案
你是对的,你不能对排序后的设置值本身“设置到期日”。
但是您可以使用主键并在到期时捕获事件。您至少有两种方法可以实现这一目标:
key 空间通知
使用 key 空间通知,您可以捕获 EXPIRE 事件,该事件将发送一条 PUBLISH 消息,然后您可以使用该消息。
让我解释一下基本流程:
配置通知
CONFIG SET notify-keyspace-events Ex
- E:按键上发生的事件
- x:捕获过期事件
现在您的数据库将在 __key*__:*
channel 上发布一个事件。
因此,您可以构建一个服务来监听这些事件更新集(直接或间接):
psubscribe __key*__:*
如果您有一个应用程序设置了以下值和过期时间
set foo bar EX 5
您应该收到以下消息
1) "pmessage"
2) "__key*__:*"
3) "__keyevent@0__:expired"
4) "foo"
Redis 齿轮
使用 Redis Gears,您可以捕获相同的事件(它也基于通知),但直接在 Redis 数据库中编写代码更容易。
您可以按如下方式创建 Gears:(这是一个 Python 脚本,我使用 RedisInsight 将其部署到 Redis)
def process(x):
execute('LPUSH', 'expired:keys', x['value']['key']);
# Capture an expiration event and adds it to 'expired:events' stream
cap = GB('KeysReader')
cap.foreach(lambda x:
execute('XADD', 'expired:events', '*', 'key', x['key']))
cap.register(prefix='*',
mode='sync',
eventTypes=['expired'],
readValue=False)
# Consume new messages from expiration streams and process them somehow
proc = GB('StreamReader')
proc.foreach(process)
proc.register(prefix='expired:*',
batch=100,
duration=1,
trimStream = False)
查看由cap = GB('KeysReader')
开始的部分
- 这将监听任何 key 过期
prefix='*'
&eventTypes=['expired']
- 如果过期,它将使用 XADD 命令向
'expired:events'
Redis Stream 添加一条消息 - 然后查看将处理流的函数
proc = GB('StreamReader')
- 每当流中出现新消息时,它都会调用
process()
函数。
您可以添加逻辑来更新此函数中的排序集。在我的示例中,我刚刚将过期 key 添加到列表中。
让我稍微偏离一下你最初的问题。
看起来您正在使用排序集为数据创建某种形式的索引。
如果是这种情况,您应该查看 RediSearch,这是另一个 Redis 模块,它允许您对 哈希 字段建立索引,然后使用该索引进行一些高级查询和聚合。
使用RediSearch,您不需要添加任何代码来管理索引,它是由数据库自动完成的,您可以对字段进行查询。
我邀请您查看:
很抱歉,如果这不是您使用排序集的原因,但我认为值得检查,因为如果您今天手动管理索引,则可以简化很多应用程序代码。
关于Redis 在键过期时更新排序集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64338227/