背景:
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版权协议,转载请附上原文出处链接和本声明。