Redis+Lua脚本模糊匹配批量删除key

背景

业务上有一批数据是按照每天的日期来进行存储的,同时也限制了队列的容量(防止大key问题),但是队列中或多或少有些数据未被消费(定时任务消费者处理不及时,跨天数据未被执行到),导致历史数据一直冗余占用内存,所以需要删除历史key,减少内存占用。

实现

首先通过特定的key类型找到需要删除的数据,业务上的key都带有日期,直接使用以下命令即可获取

keyredis执行:
keys *2023*
​
lua脚本eval "return redis.call('keys', '*2023*')"

然后将keys分批,主要是防止keys结果太大,删除任务执行太慢。– 处理查询出来的所有key 分割成batchSize一批


-- 处理查询出来的所有key 分割成batchSize一批
local function splitList(inputList, batchSize)
    local result = {}
    local currentBatch = {}

    for _, value in ipairs(inputList) do
        table.insert(currentBatch, value)

        if #currentBatch == batchSize then
            table.insert(result, currentBatch)
            currentBatch = {} -- 重置当前批次
        end
    end

    -- 处理最后一批
    if #currentBatch > 0 then
        table.insert(result, currentBatch)
    end

    return result
end

最后遍历分批处理好的table,调用UNLINK异步删除。UNLINK和DEL都可以删除key,但是DEL是阻塞的,UNLINK是开启异步线程删除的,使用UNLINK删除key不会影响主线程接受其他命令,同时开启多个异步线程也可以更快删除大Key。

-- 记录总共删除的数量
local allDeleteNum = 0
-- 遍历keys(50一组批量删除)
for _, keys in ipairs(toDeleteBatchKeys) do
   allDeleteNum = allDeleteNum + redis.call('UNLINK', unpack(keys))
end

完整代码

-- 处理查询出来的所有key 分割成batchSize一批
local function splitList(inputList, batchSize)
   local result = {}
   local currentBatch = {}
​
   for _, value in ipairs(inputList) do
       table.insert(currentBatch, value)
​
       if #currentBatch == batchSize then
           table.insert(result, currentBatch)
           currentBatch = {}  -- 重置当前批次
       end
   end
​
   -- 处理最后一批
   if #currentBatch > 0 then
       table.insert(result, currentBatch)
   end
​
   return result
end
​
​
local toDeleteKeys = redis.call('keys', KEYS[1])
local batchSize = 50
local toDeleteBatchKeys = splitList(toDeleteKeys, batchSize);
​
local allDeleteNum = 0
for _, keys in ipairs(toDeleteBatchKeys) do
   allDeleteNum = allDeleteNum + redis.call('UNLINK', unpack(keys))
end
return "DeleteNums " .. tostring(allDeleteNum)

这里同时提供一个java实现://java实现 Redisson

RScript script = redisson.getScript();
       String lua = "local function splitList(inputList, batchSize)\n" +
               "   local result = {}\n" +
               "   local currentBatch = {}\n" +
               "\n" +
               "   for _, value in ipairs(inputList) do\n" +
               "       table.insert(currentBatch, value)\n" +
               "\n" +
               "       if #currentBatch == batchSize then\n" +
               "           table.insert(result, currentBatch)\n" +
               "           currentBatch = {} \n" +
               "       end\n" +
               "   end\n" +
               "\n" +
               "   if #currentBatch > 0 then\n" +
               "       table.insert(result, currentBatch)\n" +
               "   end\n" +
               "\n" +
               "   return result\n" +
               "end\n" +
               "\n" +
               "\n" +
               "local toDeleteKeys = redis.call('keys', KEYS[1])\n" +
               "local batchSize = 50\n" +
               "local toDeleteBatchKeys = splitList(toDeleteKeys, batchSize);\n" +
               "\n" +
               "local allDeleteNum = 0\n" +
               "for _, keys in ipairs(toDeleteBatchKeys) do\n" +
               "   allDeleteNum = allDeleteNum + redis.call(\"UNLINK\", unpack(keys))\n" +
               "end\n" +
               "return \"DeleteNums \" .. tostring(allDeleteNum)";
       Object deleteNums = script.eval(RScript.Mode.READ_ONLY, lua, RScript.ReturnType.VALUE, Collections.singletonList("key"));
       log.info("{}", deleteNums);
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇