RedisTemplate加载lua脚本实现指定key删除

背景:

      RedisTemplate中批量删除可以使用redisTemplate.delete(kyes),但是前提需要进行模糊匹配即keys命令。看起来很完美,但是现实总是很残酷,在实际线上项目中不能使用,会产生性能问题会占用大量的cpu使用资源,因为redis单线程;

方案:

      1,使用scan;

      2,使用树状结构,rootkey - subkeys

      3,lua脚本(里面也是redis命令)

RedisTemplate执行lua脚本:

      redis在2.6后者更高的版本可以使用lua解释器来执行脚本从而实现原子性的操作;当然lua脚本尽可能的短并且短时间,因为慢的脚本一样会占用cup会长时间锁住;

实例:

       批量删除:

        

local function scan(key)
    local cursor = 0
    local keynum = 0

    repeat
        local res = redis.call("scan", cursor, "match", key)

        if (res ~= nil and #res >= 0) then
            redis.replicate_commands()
            cursor = tonumber(res[1])
            local ks = res[2]
            keynum = #ks
            for i=1,keynum,1 do
                local k = tostring(ks[i])
                redis.call("del", k)
            end
        end
    until (cursor <= 0)

    return keynum
end

local a = #KEYS
local b = 1
local total = 0
while (b <= a)
do
    total = total + scan(KEYS[b])
    b = b + 1
end

return total

重点:redis.replicate_commands(); 在该操作之后的命令(对库中数据产生变化的命令)别包装到一个multi/exec事务中,并发送到AOP或者从库;在这之前如果产生对库数据一致性产生破坏的操作redis.replicate_commands不会生效;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class RedisUtils
{
    @Autowired
    private StringRedisTemplate redisTemplate;

    public Object runLuaScript(String scriptFile, List<String> keys)
    {
        Resource resource = new ClassPathResource(scriptFile);
        ResourceScriptSource scriptSource = new ResourceScriptSource(resource);
        DefaultRedisScript script = new DefaultRedisScript();
        script.setScriptSource(scriptSource);
        script.setResultType(String.class);
        return redisTemplate.execute(script, keys);
    }
}

此处加载lua脚本并执行


版权声明:本文为zhyilong原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。