在我的Redis DB中,我有一些前缀:<numeric_id>哈希值。
有时我想把它们都原子地清除掉。如何在不使用分布式锁定机制的情况下做到这一点呢?
在我的Redis DB中,我有一些前缀:<numeric_id>哈希值。
有时我想把它们都原子地清除掉。如何在不使用分布式锁定机制的情况下做到这一点呢?
当前回答
免责声明:以下解决方案不提供原子性。
从v2.8开始,您确实希望使用SCAN命令而不是KEYS[1]。下面的Bash脚本演示了按模式删除键:
#!/bin/bash
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 ]\)'`
keys=${reply##[0-9]*[0-9 ]}
redis-cli -h $1 -p $2 DEL $keys
done
[1] KEYS是一个可能导致DoS的危险命令。以下摘自其文档页面:
警告:将KEYS视为只应在生产环境中极其小心地使用的命令。当它针对大型数据库执行时,可能会破坏性能。此命令用于调试和特殊操作,例如更改密钥空间布局。不要在常规应用程序代码中使用key。如果您正在寻找一种在键空间子集中查找键的方法,请考虑使用集合。
更新:一个班轮相同的基本效果-
$ redis-cli --scan --pattern "*:foo:bar:*" | xargs -L 100 redis-cli DEL
其他回答
再加上这个答案:
要找到前1000个键:
EVAL "return redis.call('scan', 0, 'COUNT', 1000, 'MATCH', ARGV[1])" 0 find_me_*
删除它们:
EVAL "return redis.call('del', unpack(redis.call('SCAN', 0, 'COUNT', 1000, 'MATCH', ARGV[1])[2]))" 0 delete_me_*
如果你的键名中有空格,这将适用于MacOS
redis-cli --scan --pattern "myprefix:*" | tr \\n \\0 | xargs -0 redis-cli unlink
这并不是对这个问题的直接回答,但因为我是在寻找自己的答案时来到这里的,所以我将在这里分享。
如果你有数千万或数亿个键需要匹配,这里给出的答案将导致Redis在很长一段时间内(几分钟?)没有响应,并可能因为内存消耗而崩溃(当然,后台保存将在你的操作过程中启动)。
下面的方法不可否认是丑陋的,但我没有找到更好的方法。原子性在这里是没有问题的,在这种情况下,主要目标是保持Redis的正常运行和100%的响应。如果您将所有的密钥都放在一个数据库中,并且不需要匹配任何模式,那么它将完美地工作,但不能使用http://redis.io/commands/FLUSHDB,因为它具有阻塞特性。
想法很简单:写一个脚本,在循环中运行,使用O(1)操作,如http://redis.io/commands/SCAN或http://redis.io/commands/RANDOMKEY来获取密钥,检查它们是否匹配模式(如果你需要的话),然后逐个http://redis.io/commands/DEL它们。
如果有更好的方法,请告诉我,我会更新答案。
Ruby中使用randomkey的示例实现,作为rake任务,以非阻塞方式代替redis-cli -n 3 flushdb:
desc 'Cleanup redis'
task cleanup_redis: :environment do
redis = Redis.new(...) # connection to target database number which needs to be wiped out
counter = 0
while key = redis.randomkey
puts "Deleting #{counter}: #{key}"
redis.del(key)
counter += 1
end
end
/ /所有
你认为这是没有意义的命令,但有时Redis命令像DEL不能正确工作,来拯救这个
redis-cli KEYS "*" | xargs -i redis-cli EXPIRE {} 1 it's life hack
如果你在键的名称中有空格,你可以在bash中使用:
redis-cli keys "pattern: *" | xargs -L1 -I '$' echo '"$"' | xargs redis-cli del