线上Redis存在大量不常用的冗余的值,对服务器的内存造成浪费,所以优化存入和过期逻辑,并手动清理无用的值。
一.登录Redis控制台
我们可以直接登录到redis控制台,使用原声的命令来执行删除(如DEL
、KEYS
等),但是不支持复杂的用法,也就是无法模糊的查询key进行批量删除。
参考:Redis官方命令地址
二.Redis客户端工具
Redis支持多种客户端工具,除了开发语言外,比较常用的是一款名为RedisCli的工具,实现根据key模糊删除的语句如下:
redis-cli -h 127.0.0.1 -p 6379 -a yourpassword keys "keyword*" |xargs redis-cli -h 127.0.0.1 -p 6379 -a youpassword del
-h指定host地址,默认127.0.0.1
-p指定port,默认6379
-a指定redis密码
keyword为指定的key的模糊关键词,*
代表通配符。
这个命令使用的redis的命令是del,这种删除方式如果删除大批量的值会存在阻塞问题,因此生产环境是不推荐使用的;并且我执行上面命令没有成功,提示del缺少参数。因此上述命令只是作为记录和参考。
三.使用Redis的EVAL执行Lua脚本方式
redis 2.6.0 之后的版本支持通过 EVAL 或 EVALSHA 执行使用Lua。 可以保证操作的原子性,还可以通过
script load
对脚本进行缓存,减少网络开销。使用lua 有更高的自由度,可以添加很多功能模块。redis2.8.0之后使用SCAN替代KEYS,对大批量的查询进行了优化,不会阻塞主进程
并且新版本(4.0.0之后)的redis使用UNLINK代替DEL命令。UNLINK会在另一个线程中执行内存的回收,不会阻塞正常的get set请求。
也就是本文采用的查询和删除方式。
lua的文件如下:
-- 选择要操作的数据库
redis.call("select",7)
--游标的id
local cursor = 0
--查找删除的key的数量
local keyNum = 0
repeat
--使用scan搜索,cursor=0的时候标识一个新的迭代期,服务器返回0的时候表示迭代已经结束
local res = redis.call("scan",cursor,"MATCH",KEYS[1])
if(res ~= nil and #res>=0) then
cursor = tonumber(res[1])
local ks = res[2]
if(ks ~= nil and #ks>0) then
redis.replicate_commands()
--循环删除当前迭代器迭代出的数据
for i=1,#ks,1 do
local key = tostring(ks[i])
--使用UNLINK删除,区别于del的是这个是异步执行的
--这条指令要版本大于4.0.0 小于4.0.0就使用del
redis.call("UNLINK",key)
end
--统计删除的key的数量
keyNum = keyNum + #ks
end
end
--当服务器返回0的时候,跳出循环
until( cursor <= 0 )
return keyNum
通过redis-cli执行脚本
# 通过redis-cli执行脚本
redis-cli -h 地址 -p 端口 -a 密码 --eval 以上创建文件的路径/clear_data.lua "需要删除的key的前缀_*"
# 多值传送示例
redis-cli -h 地址 -p 端口 -a 密码 --eval 以上创建文件的路径/clear_data.lua "key1" "key2" , "va1" "va2"
# 脚本调用示例
redis-cli -h 127.0.0.1 -p 6379 -a 123456789 --eval /usr/local/redis/clear_data.lua "test_*"
参考文章: