首先有一个业务场景是使用用户唯一标识作为key的前缀比如:
userId:token:xxxxxxxxx 或者userId:xxxxx:xxxxx 这种缓存的数据虽然有过期时间但是如果需要要在业务场景中需要批量删除而且Redis库中的数据很多、然后以userId为前缀的key又很多的话就需要批量删除,但是需要考虑原子性,那就又要用到Lua脚本了。废话不多说直接上代码
java
// 首先要注入起一个另外的名字 构造参数注入方式
private final RedisTemplate<String, String> luaRedisTemplate;
/**
* 根据key模糊匹配删除缓存
*
* @param pattern key前缀
*/
public void deleteByPatternLua(String pattern) {
try {
log.info("开始删除匹配模式的键: {}", pattern);
String luaScript = "local pattern = ARGV[1]\n"
+ "local cursor = '0'\n"
+ "local deleted = 0\n"
+ "local loop_count = 0\n"
+ "repeat\n"
+ " loop_count = loop_count + 1\n"
+ " local result = redis.call('SCAN', cursor, 'MATCH', pattern, 'COUNT', 1000)\n"
+ " cursor = result[1]\n"
+ " local keys = result[2]\n"
+ " if #keys > 0 then\n"
+ " local del_result = redis.call('DEL', unpack(keys))\n"
+ " deleted = deleted + del_result\n"
+ " end\n"
+ " if loop_count > 1000 then break end\n"
+ "until cursor == '0'\n"
+ "return deleted";
DefaultRedisScript<Long> script = new DefaultRedisScript<>();
script.setScriptText(luaScript);
script.setResultType(Long.class);
// 使用luaRedisTemplate执行Lua脚本否则无法删除
Long result = luaRedisTemplate.execute(script, Collections.emptyList(), pattern);
log.info("删除匹配模式 {} 的键完成,实际删除数量: {}", pattern, result);
} catch (Exception e) {
log.error("通过key前缀删除键失败,pattern: {}", pattern, e);
throw new I18nServiceException(INTERNAL_SERVER_ERROR);
}
}