redis存储了很多无用的key,占用了大量内存,需要清除
第一种 (颗粒度较大)
lua脚本,删除某些规则的key,输入删除的key,返回删除的符合规则的key的数量
弊端:颗粒度比较大,发送一个lua脚本去执行,会占用较多时间,堵塞其他redis命令
local function scan(key)local cursor = 0local keynum = 0repeatlocal res = redis.call("scan", cursor, "match", key, "COUNT", ARGV[1])if(res ~= nil and #res >= 0) thenredis.replicate_commands()cursor = tonumber(res[1])local ks = res[2]local keynum1 = #kskeynum = keynum + keynum1for i=1,keynum1,1 dolocal k = tostring(ks[i])redis.call("del", k)endenduntil(cursor <= 0)return keynum
endlocal a = #KEYS
local b = 1
local total = 0
while(b <= a)
do total = total + scan(KEYS[b])b=b+1
endreturn total
java代码
String delLua = "local function scan(key)\n" +"\tlocal cursor = 0\n" +"\tlocal keynum = 0\n" +"\trepeat\n" +"\t\tlocal res = redis.call(\"scan\", cursor, \"match\", key, \"COUNT\", ARGV[1])\n" +"\t\tif(res ~= nil and #res >= 0) then\n" +"\t\t\tredis.replicate_commands()\n" +"\t\t\tcursor = tonumber(res[1])\n" +"\t\t\tlocal ks = res[2]\n" +"\t\t\tlocal keynum1 = #ks\n" +"\t\t\tkeynum = keynum + keynum1\n" +"\t\t\tfor i=1,keynum1,1 do\n" +"\t\t\t\tlocal k = tostring(ks[i])\n" +"\t\t\t\tredis.call(\"del\", k)\n" +"\t\t\tend\n" +"\t\tend\n" +"\tuntil(cursor <= 0)\n" +"\treturn keynum\n" +"end\n" +"\n" +"local a = #KEYS\n" +"local b = 1 \n" +"local total = 0\n" +"while(b <= a)\n" +"do \n" +"\ttotal = total + scan(KEYS[b])\n" +"\tb=b+1\n" +"end\n" +"\n" +"return total";
// 指定 lua 脚本,并且指定返回值类型
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(delLua, Long.class);
// 参数一:redisScript,参数二:key列表,参数三:arg(可多个)
long start = System.currentTimeMillis();
Long result = (Long) redisTemplate.execute(redisScript, Collections.singletonList(scenicId + ":*"), 20000);
long end = System.currentTimeMillis();
这样直接删除,因为规则有很多个,需要循环删除,每一次调用脚本都需要占用redis一分多时间,
第二种(切割所有key,每次返回指定数量,然后过滤删除)
lua脚本
local cursor = ARGV[1]
local result = redis.call('SCAN', cursor, 'COUNT', 10000)
return {result[1], result[2]}
// Lua脚本用于SCAN操作,获取指定数量的key
String luaScript = "local cursor = ARGV[1]\n" +"local result = redis.call('SCAN', cursor, 'COUNT', 10000)\n" +"return {result[1], result[2]}";// 创建Redis脚本对象
DefaultRedisScript<List> defaultRedisScript = new DefaultRedisScript<>(luaScript, List.class);
defaultRedisScript.setResultType(List.class);Integer cursorInt = 0;
String newCursor = cursorInt.toString(); // 初始游标// 参数:cursor初始为0,match为""表示匹配所有key,count为1000
List<Object> keys = stringRedisTemplate.execute(defaultRedisScript, Collections.emptyList(), newCursor);
// 解析结果
newCursor = keys.get(0).toString(); // 新的cursor
List<String> keyList = (List<String>)keys.get(1);
//对获取出来的key进行规则筛选,查看那些可以直接删除
//过滤逻辑 和 删除