SpringでRedis Luaスクリプトを使用してキャッシュを一括削除する
7295 ワード
背景
前にluaスクリプトを利用してredisのkeyを一括削除する文章を共有した.今プロジェクトではspringのキャッシュを使うつもりですが、Springキャッシュは以前ehcacheで実現していました.何の問題も見つからなかった..今度はredisに変えてキャッシュしました.普通は大した問題はありませんが...現在唯一遭遇している比較ピットの問題は、キャッシュが注釈で削除できないことです.私も普通だと思います.Javaの中でキャッシュをするとmapのような構造を使うかもしれないので、私はremoveでkeyを削除して、対応するvalueがどんな構造であれ削除することができます..しかしredisのkeyには階層がありません...例えば2つのkeyはそれぞれa:a 1とa:a 2である.ビジュアル化ツールではaの下に属しているように見えますが..しかしredisのdel aはa部下のすべてのkeyを削除するのではなく、keyがaであるこのデータだけを削除する.Spring Cacheでキャッシュを削除する論理を自分で実現しなければなりませんredis自体はkeyを一括削除する機能はない.
に質問
そこで今の問題はSpringのredisTemplateでluaスクリプトを使用してkeyを削除する方法です
解決策
できると思います.
1.まず、前の文章で書いた大量削除のluaスクリプトをmavenプロジェクトのresourcesの下に置く.
2.次にBean implements InitializingBeanが起動時にこれらのスクリプトをロードすることを書く.
3.一括削除が必要な場合はこのスクリプトをDefaultRedisScriptで使用する
これにより、Javaコードでluaスクリプトを使用するキャッシュの一括削除に成功する.
一部の子供は聞くかもしれません.このようにするには、毎回スクリプトをredisにシーケンス化する必要がありますか?スクリプトが大きくなるとネットワークが占有されるのではないでしょうか.
実は...
DefaultScriptExecutorには次のコードがあります.
このスクリプトのsha 1の値を先に計算し、redisのEVALSHAでスクリプトを許可します.失敗すると、例えば初めてロードされなかった.スクリプトをシーケンス化して実行します...以降はこのsha 1値で直接呼び出す.
小結
DefaultRedisScriptを使用すると、javaでluaスクリプトを使用してredisを操作するのに便利です.
前にluaスクリプトを利用してredisのkeyを一括削除する文章を共有した.今プロジェクトではspringのキャッシュを使うつもりですが、Springキャッシュは以前ehcacheで実現していました.何の問題も見つからなかった..今度はredisに変えてキャッシュしました.普通は大した問題はありませんが...現在唯一遭遇している比較ピットの問題は、キャッシュが注釈で削除できないことです.私も普通だと思います.Javaの中でキャッシュをするとmapのような構造を使うかもしれないので、私はremoveでkeyを削除して、対応するvalueがどんな構造であれ削除することができます..しかしredisのkeyには階層がありません...例えば2つのkeyはそれぞれa:a 1とa:a 2である.ビジュアル化ツールでは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 sc = new DefaultRedisScript<>(s, List.class);
17 scripts.put("dels", sc);
18 }
3.一括削除が必要な場合はこのスクリプトをDefaultRedisScriptで使用する
1 DefaultRedisScript sc = scripts.get("dels");
2 List cache = (List) redisTemplate.execute(sc, stringRedisSerializer, stringRedisSerializer, Collections.singletonList(wholeKey));
3 log.info(" page {}", cache);
これにより、Javaコードでluaスクリプトを使用するキャッシュの一括削除に成功する.
一部の子供は聞くかもしれません.このようにするには、毎回スクリプトをredisにシーケンス化する必要がありますか?スクリプトが大きくなるとネットワークが占有されるのではないでしょうか.
実は...
DefaultScriptExecutorには次のコードがあります.
1 protected T eval(RedisConnection connection, RedisScript script, ReturnType returnType, int numKeys,
2 byte[][] keysAndArgs, RedisSerializer 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 }
このスクリプトのsha 1の値を先に計算し、redisのEVALSHAでスクリプトを許可します.失敗すると、例えば初めてロードされなかった.スクリプトをシーケンス化して実行します...以降はこのsha 1値で直接呼び出す.
127.0.0.1:6379> SCRIPT EXISTS f7cb6ede3d6d2e14b812f32f129633443197b42c
1) (integer) 1
小結
DefaultRedisScriptを使用すると、javaでluaスクリプトを使用してredisを操作するのに便利です.