Redis 的 Lua 脚本实例

1、统计以‘TMP_MP_TOKEN_INFO:’为前缀的key的个数

EVAL "
    -- 初始化统计变量
    local count = 0          -- key总数
    local total_mem = 0      -- 总内存占用(字节)
    local cursor = '0'       -- SCAN游标初始值
    local pattern = ARGV[1]  -- 从外部传参获取要匹配的前缀

    -- 循环遍历所有匹配的key(非阻塞SCAN)
    repeat
        -- 执行SCAN命令:游标、匹配模式、单次扫描数量(优化为1000,提升效率)
        local scan_result = redis.call('SCAN', cursor, 'MATCH', pattern, 'COUNT', 1000)
        cursor = scan_result[1]  -- 更新游标
        local keys = scan_result[2]  -- 获取本次扫描到的key列表

        -- 遍历本次获取的key,统计数量和内存
        for _, key in ipairs(keys) do
            count = count + 1
            -- 【修复问题2】增加异常处理,避免key不存在导致脚本终止
            local mem = 0
            local ok, res = pcall('MEMORY', 'USAGE', key)
            if ok then
                mem = res  -- key存在,取实际内存占用
            else
                mem = 0    -- key不存在,内存计为0
                redis.log(redis.LOG_WARNING, 'Key ' .. key .. ' not found, skip memory count')
            end
            total_mem = total_mem + mem
        end
    until cursor == '0'  -- 游标为0时遍历完成

    -- 【修复问题3】优化单位转换,兼容total_mem=0的情况
    local total_mb = 0.00
    if total_mem > 0 then
        total_mb = string.format('%.2f', total_mem / 1024 / 1024)
    else
        total_mb = '0.00'
    end

    -- 返回统计结果
    return {
        '前缀:' .. pattern,
        'key总数:' .. tostring(count),  -- 显式转字符串,避免类型不一致
        '总内存占用(字节):' .. tostring(total_mem),
        '总内存占用(MB):' .. total_mb
    }
" 1 "TMP_MP_TOKEN_INFO:placeholder" "TMP_MP_TOKEN_INFO:*"

2、查看以‘TMP_MP_TOKEN_INFO:’为前缀的key的前3个key

EVAL "
    local target_prefix = 'TMP_MP_TOKEN_INFO:'
    local max_count = 3
    local cursor = '0'
    local result = {}

    repeat
        local scan_result = redis.call('SCAN', cursor, 'MATCH', target_prefix .. '*', 'COUNT', 100)
        cursor = scan_result[1]
        local keys = scan_result[2]

        for _, key in ipairs(keys) do
            table.insert(result, key)
            if #result >= max_count then
                break
            end
        end
    until cursor == '0' or #result >= max_count

    local final_result = {}
    for i=1, math.min(max_count, #result) do
        table.insert(final_result, result[i])
    end

    return final_result
" 1 "TMP_MP_TOKEN_INFO:placeholder"

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注