在Spring中使用Redis Lua脚本批量删除缓存
2018-02-01 10:03
786 查看
背景
之前分享了一篇利用lua脚本批量删除redis的key的文章.现在项目中我打算使用spring的缓存,而Spring缓存以前我是用ehcache来做实现的.没发现什么问题..这次我换成redis来做缓存了..一般也没什么大问题...目前唯一遇到的一个比较坑的问题就是缓存通过注解删除不了..我想想好像也算正常吧.因为java里面做缓存的话可能会使用map类似的结构,我remove掉一个key,不管对应的value是什么结构都能删除掉..但是redis的key是没有层级的...比如2个key分别是a:a1和a:a2.虽然可视化工具上看上去都是属于a下面的..但是redis的del a并不会删除a下属的所有key而是只会删除key为a的这个数据.所以我得自己实现Spring Cache中删除缓存的那部分逻辑.而redis本身是没有批量删除key的功能的.问题
所以现在的问题就是 如何在Spring的redisTemplate中使用lua脚本删除key解决办法
我觉得可以这么做:1.首先把之前文章写的批量删除的lua脚本放到maven项目的resources下.
2.然后写一个Bean implements InitializingBean在启动的时候加载这些脚本.
1 /** 2 * 加载批量lua脚本 3 * 4 * @throws Exception 5 */ 6 @Override 7 public void afterPropertiesSet() throws Exception { 8 loadDelScript(); 9 } 10 11 /** 12 * 加载批量删除脚本 13 */ 14 private void loadDelScript() throws IOException { 15 String s = FileUtils.readFileToString(new ClassPathResource(CRedisCacheConstant.SCRIPT_PATH + "/" + "dels.lua").getFile(), Charset.forName("UTF-8")); 16 DefaultRedisScript<List> sc = new DefaultRedisScript<>(s, List.class); 17 scripts.put("dels", sc); 18 }
3.需要批量删除的时候通过DefaultRedisScript去使用这个脚本
1 DefaultRedisScript<List> sc = scripts.get("dels"); 2 List<String> cache = (List<String>) redisTemplate.execute(sc, stringRedisSerializer, stringRedisSerializer, Collections.singletonList(wholeKey)); 3 log.info("删除page缓存 {}", cache);
这样就可以在Java代码中使用lua脚本成功批量删除缓存啦.
有些小朋友可能会问.这样做每次都需要把脚本序列化传给redis吗?那脚本大了不是很占用网络吗?
其实并不会...
DefaultScriptExecutor中有一段代码:
1 protected <T> T eval(RedisConnection connection, RedisScript<T> script, ReturnType returnType, int numKeys, 2 byte[][] keysAndArgs, RedisSerializer<T> resultSerializer) { 3 4 Object result; 5 try { 6 result = connection.evalSha(script.getSha1(), returnType, numKeys, keysAndArgs); 7 } catch (Exception e) { 8 9 if (!exceptionContainsNoScriptError(e)) { 10 throw e instanceof RuntimeException ? (RuntimeException) e : new RedisSystemException(e.getMessage(), e); 11 } 12 13 result = connection.eval(scriptBytes(script), returnType, numKeys, keysAndArgs); 14 } 15 16 if (script.getResultType() == null) { 17 return null; 18 } 19 20 return deserializeResult(resultSerializer, result); 21 }
会先计算这个脚本的sha1的值,通过redis的EVALSHA去允许脚本..如果失败了,比如第一次没有加载.就把脚本序列化传过去执行...往后都通过这个sha1值直接调用.
127.0.0.1:6379> SCRIPT EXISTS f7cb6ede3d6d2e14b812f32f129633443197b42c 1) (integer) 1
小结
通过使用DefaultRedisScript可以比较方便的在java中使用lua脚本操作redis相关文章推荐
- 1 Springboot中使用redis,自动缓存、更新、删除
- StackExchange.Redis加载Lua脚本进行模糊查询的批量删除和修改
- StackExchange.Redis加载Lua脚本进行模糊查询的批量删除和修改
- StackExchange.Redis加载Lua脚本进行模糊查询的批量删除和修改
- Redis整合Spring结合使用缓存实例
- Redis学习总结(3)——Redis整合Spring结合使用缓存实例
- Redis整合Spring结合使用缓存实例
- 使用spring-data-redis做缓存
- 深入理解Spring Redis的使用 (四)、RedisTemplate执行Redis脚本
- 使用Spring Data Redis实现缓存遇到的一些问题
- redis实现附近的人,但jedis中没有相关api,那么直接使用lua脚本执行。
- Redis整合Spring结合使用缓存实例
- spring-data-redis 自定义缓存(@annotation+lua+aop)(一)
- Spring Boot使用redis做数据缓存
- Spring Boot使用redis做数据缓存
- 在redis一致性hash(shard)中使用lua脚本的坑
- Redis整合Spring结合使用缓存实例
- Redis整合Spring结合使用缓存实例(转)
- PHP中使用redis执行lua脚本示例
- Redis整合Spring结合使用缓存实例(三)