Redis:如何删除与模式匹配的多个键?

7

我需要删除10,000个键。

  1. 更好的方式是执行这种脚本:

    EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 "ROOT"

  2. 也许更好的方法是设置过期时间,让Redis自己移除它们?但是如何在控制台中使用Lua脚本实现呢?

上面的脚本之所以有效是因为“del”命令有一个格式:

del key1 key2 ...

但是过期仅适用于 1 个键。

在 Lua 脚本中是否可以实现?

例如:我的应用程序创建了一些搜索结果缓存,并为每个页面设置了 ttl = 3600。但用户想要立即清除缓存,即删除所有匹配的键或为它们设置更短的过期时间。


在推荐处理此事的方法之前,您是否需要一次性删除所有密钥,还是您的要求更为宽松? - Itamar Haber
我想在具有GUI的C#应用程序中执行此命令(批处理?)。 - ZedZip
你知道原子操作会在 Redis 服务器运行时阻塞它,这符合要求(即不要在需要保持 Redis 可用以服务请求的环境中运行),对吗? - Itamar Haber
是的,你说得对。但我不想在客户端应用程序中运行循环,因为这将不是最优和长时间操作。我需要为匹配某些模式的多个键设置过期时间。我发现在我的示例中使用“keys”也不是一个好的解决方案。还有什么别的办法吗? - ZedZip
6个回答

11

您可以使用(从 Redis CLI)删除所有键:

flushall

或者在命令行(bash)中运行此命令

redis-cli --scan --pattern aihello_user* | xargs redis-cli del 

1
第二个命令应该是被接受的答案。它将仅删除与提供的模式匹配的键,而不影响其余数据。 - pofqggg
1
我会使用unlink而不是del,因为它是非阻塞的。解释:https://redis.io/commands/unlink - devio
redis-cli --scan --pattern aihello_user* | xargs redis-cli del {} - julius patta
在使用带有zsh的MacOS时,我必须向模式添加引号,就像这样:redis-cli --scan --pattern "workflow-status-*" | xargs redis-cli del - Mahad Ahmed

8
如果您想删除一个匹配前缀的键,那么可以尝试以下命令。
redis-cli keys <PREFIX>'*' | xargs redis-cli del

这里的 keys <PREFIX> '*' 将会返回与该前缀匹配的所有键,然后使用del命令将其全部删除。


4
无论您是 DEL 还是 EXPIRE,一旦 Lua 脚本运行,它将阻塞其他客户端,并且如果运行时间过长,则会超时 lua-time-limit。尽管您不愿循环,我强烈建议您这样做。
到期与删除可能会减轻一些即时负载(尚未经过实证),因此可以选择其中一个。在任一情况下,在 SCAN 操作上使用客户端循环来调用每个键的命令。如果您的架构中有一个服务器/工作进程,则可以考虑委托此任务,以便客户端不会忙于此。
根据评论进行编辑:可变参数命令(例如 DEL)通常比非可变参数命令更高效,但在此处您正在比较两个不同的操作,因此没有保证。 DEL 方法潜在地更加阻塞,因为 Redis 实际上会立即删除键 - 如果要删除的键很多和/或它们的值很大,则可能需要更长时间。 EXPIRE 方法通过利用 Redis 的懒惰到期机制(在可能的情况下使用空闲时间)来试图避免这种情况,因此,由于到期而删除的负载理论上更好地分布。确定哪种方法对您的工作效果更好的最佳方法是测试两种方法并进行比较-我很想了解您的结果!

好的,谢谢。还有一个问题。我的任务是删除键。好的, 1)我使用 SCAN 并为每个记录调用 EXPIRE。很清楚。2)但是,我可以在循环中为键的子集调用 DEL 而不是 EXPIRE。哪种方法更快、更优化和更少锁定? - ZedZip

0
我一直在寻找这个,最终编写了一个Bash脚本,它接受主机、端口和模式。看起来很有效。这是Gist的链接。
if [ $# -ne 3 ] 
then
  echo "Delete keys from Redis matching a pattern using SCAN & DEL"
  echo "Usage: $0 <host> <port> <pattern>"
  exit 1
fi

cursor=-1
keys=""

while [ $cursor -ne 0 ]; do
  if [ $cursor -eq -1 ]
  then
    cursor=0
  fi

  reply=`redis-cli -h $1 -p $2 SCAN $cursor MATCH $3`
  cursor=`expr "$reply" : '\([0-9]*[0-9 ]\)'`
  if [[ $reply = *[[:space:]]* ]]
  then
    keys=${reply#[0-9]*[[:space:]]}
    for key in $keys; do
      echo "Delete the following key: $key"
      redis-cli -h $1 -p $2 DEL $key 
    done
  fi
done

0
redis-cli -h 127.0.0.1 -p 6379 --scan --pattern <pattern>* | xargs redis-cli unlink 

使用scan和unlink函数不是阻塞函数


0

以下是您如何通过CLI批量过期的方法:

EVAL 'for i, name in ipairs(redis.call("KEYS", <pattern>)) do redis.call("EXPIRE", name, 1); end' 0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接