我想模糊删除redis key🤔
前提
redis中存在很多key,可能随着业务的下架永远也用不到了,需要批量删除(当然也可以不处理,等redis内存不足的时候,自动去执行淘汰策略)。假设存在若干个如下模式的key,都是以 unkey 为前缀,现在希望批量删除。

redis 2.6.0 之前
通过 直接删除(不推荐)
redis官方中的 是不支持正则表达式的,但是你可以从网上找到相关的办法让 命令支持正则,因为不推荐,所有不展示
通过 实现
redis中的 是支持通过正则表达式获取匹配的key,然后通过管道传递给 进行删除
redis-cli KEYS "unkey*" | xargs redis-cli DEL

redis 2.6.0 之后
通过Lua脚本删除
redis 2.6.0 之后的版本支持通过 或 执行使用Lua。 可以保证操作的原子性,还可以通过 对脚本进行缓存,减少网络开销。使用lua 有更高的自由度,可以添加很多功能模块。
return redis.call('del',unpack(redis.call('keys','unkey*')))
基本流程是这样的,如果逻辑严谨的话,可以动态传入匹配的表达式,返回删除的key之类的逻辑。
-- 参数1: “un*” 正则表达式
local keys=redis.call('keys',ARGV[1]);
if #keys==0 then
return '--No match--'
else
redis.call('del',unpack(keys))
return keys
end

redis 2.8.0 之后
通过 替代
redis的执行是单线程的(至少当前版本是),如果我们通过 去批量的获取key,如果数量很大的话,会有问题:
如果我们用 替代的话,就会好很多:
-- 参数1: “un*” 正则表达式
-- 每次获取1000条(不一定返回1000条),进行删除
local cursor="0";
repeat
local t = redis.call('scan',cursor,'match',ARGV[1],'count',1000);
local list=t[2];
if #list==0 then
return '--over--'
end
redis.call('del',unpack(list));
cursor=t[1];
until cursor=="0"
return "over";
但是这样写是有问题的,这还是一次获取所有key,虽然每次都获取1000条,但是lua代码原子执行,还是会有一次获取很多阻塞线程的问题。
所有建议控制 每次获取的数量,然后多次执行,每次返回的游标给下次执行使用。
-- 参数1: “0” 游标
-- 参数2: “un*” 正则表达式
local t = redis.call('scan',ARGV[1],'match',ARGV[2],'count',1000);
local list=t[2];
if #list==0 then
return '--over--'
end
redis.call('del',unpack(list));
return t[1];
redis 4.0.0 之后
通过 替代
正常的 是在主线程内执行,等待当前的 执行完成,下一个命令才会执行。而redis在4.0之后提供了更好的选择。
会在另一个线程中执行内存的回收,不会阻塞正常的get set请求,而且使用的方式也很简单,跟执行 一样。
所以说redis 4.0 之后就不再是单线程了,但是基本的操作还是在主线程内执行。
-- 参数1: “0” 游标
-- 参数2: “un*” 正则表达式
local t = redis.call('scan',ARGV[1],'match',ARGV[2],'count',1000);
local list=t[2];
if #list==0 then
return '--over--'
end
redis.call('unlink',unpack(list));
return t[1];