ehcacheぼかし大量にキャッシュを削除する方法


前言
ご存知のように、encacheは今最も流行っているjavaオープンソースキャッシュのフレームワークで、構成は簡単で、構造がはっきりしていて、機能が強いです。注釈@Cachebaleにより、方法結果をキャッシュに素早く追加することができます。@Cacheevictを通じて指定されたキャッシュを素早く消去することができます。
しかし@Cacheevictの注釈はkey-valueを使っていますので、あいまいな削除をサポートしないと問題になります。@Cachebaleを使ってSpring EL表現に合わせて、同じ方法の複数のキャッシュを追加しました。

@GetMapping("/listOfTask/{page}/")
@Cacheable(value = "BusinessCache", key = "'listOfTask_'+ #page")
public ResponseMessage<PageTaskVO> getTaskList(@PathVariable("page") String page) {
  do something...
}
上記のコードは、ページごとにジョブ情報を取得するものです。EL式でパラメータの中のpageを取得し、キャッシュのkeyとして@Cachebaleを使ってehcacheのキャッシュに追加します。このとき、キャッシュにlistOfTask_が現れます。1,listOfTask_2,listOfTask_3このタイプのキーです。
タスクを追加、削除すると、リストが変わります。その時は、listOfTask(*)を関連するキャッシュはすべて削除します。この時、キャッシュの中でどれぐらいキャッシュされていますか?関連する内容は、@Cacheevictを呼び出して逐次削除することはできません。
ehcache自身が支持できない以上、私達自身で実現するしかないです。
実現する
使用した注釈付加のキャッシュを考慮すると、削除キャッシュも注釈処理を使用して、開発の一貫性を維持することができる。注釈は開発者にとっても友好的です。そこで、ユーザー定義の注釈を使って、バッファをぼかしたり消したりすることを考えます。
まず、注釈CacheRemoveを定義します。

@Target({ java.lang.annotation.ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface CacheRemove {
  String value();
  String[] key();
}
ここで、valueはehcacheと同様に、動作するキャッシュ名を定義するために使用される。keyは、複数のキャッシュキーを格納するための行列の正規表現です。名前をつけたCacheRemoveは分かりやすく、ehcache自身の注釈と衝突しません。注の定義はここまでです。続いて、注解が必要です。使うスプリングフレームは自然なので、AOPで注解をしたいと思います。
コメントの目的は、一括ぼかしでキャッシュを削除することです。次の二つの問題を考慮する必要があります。
  • はどんな方式でマッチングしますか?
  • どうやって一括でkey
  • を削除しますか?
    私が提示した処理方法は、最も簡単な処理方法だと思います。
  • はどのような方法で曖昧にマッチングしますか?
  • どのように大量にkeyを削除しますか?サイクルのすべてのkey、正則に合致するのを見つけたら
  • を削除します。
    最初にクラス名のCacheRemoveAspectを定義します。
    
    @Aspect
    @Component
    public class CacheRemoveAspect {
      @Pointcut(value = "(execution(* *.*(..)) && @annotation(com.example.CacheRemove))")
      private void pointcut() {}
    
      do something...
    }
    
    
    接面において接点を定義し、execution(*.*)&@annotation(comp.example.C.acheremove)を使用して、すべての注釈付きCacheRemoveが実行されることを表します。@annotationの値は注釈の全制限命名名です。
    カットポイントの定義が終わりました。次の重要シーンはカットの具体的な実現です。一般的には、キャッシュは添削の方法で実行された後に削除されます。だから@AfterReturning()を使って実現します。具体的な実現には次のようなことが必要です。
  • ブロッキング方法における注釈
  • は注釈がCacheRemove
  • であるかどうかを判断する。
  • は、注釈が入ってくるkeyが配列であるため、各key
  • をループ処理する。
  • は、サイクルで各keyを作成し、すべてのキャッシュを巡回し、マッチングしたキャッシュ
  • を除去する。
    具体的な実現は以下の通りです。
    
    @AfterReturning(value = "pointcut()")
    private void process(JoinPoint joinPoint){
      MethodSignature signature = (MethodSignature) joinPoint.getSignature();
      Method method = signature.getMethod();
      CacheRemove cacheRemove = method.getAnnotation(CacheRemove.class);
    
      if (cacheRemove != null){
        String value = cacheRemove.value();
        String[] keys = cacheRemove.key(); //       key
    
        List cacheKeys = CacheUtils.cacheKeys(value);
        for (String key : keys){
          Pattern pattern = Pattern.compile(key);
          for (Object cacheKey: cacheKeys) {
            String cacheKeyStr = String.valueOf(cacheKey);
            if (pattern.matcher(cacheKeyStr).find()){
              CacheUtils.remove(value, cacheKeyStr);
            }
          }
        }
      }
    }
    
    
    以上、ehcacheの曖昧な一括除去キャッシュの具体的な実現です。その中のBusiness CacheUtilsは自分のためにカプセル化したehcacheツール類です。主にキャッシュを取得し、キャッシュを取得し、キャッシュを除去し、キャッシュを追加し、すべてのキャッシュを表示するなどの正常な機能を実現します。コードは以下の通りです
    
    public class CacheUtils {
    
      private static CacheManager cacheManager = SpringContextHolder.getBean("ehCacheManagerFactory");
    
      public static Object get(String cacheName, String key) {
        Element element = getCache(cacheName).get(key);
        return element == null ? null : element.getObjectValue();
      }
    
      public static void put(String cacheName, String key, Object value) {
        Element element = new Element(key, value);
        getCache(cacheName).put(element);
      }
    
      public static void remove(String cacheName, String key) {
        getCache(cacheName).remove(key);
      }
    
      public static List cacheKeys(String cacheName){
        return getCache(cacheName).getKeys();
      }
    
      /**
       *     Cache,       。
       * @param cacheName
       * @return
       */
      private static Cache getCache(String cacheName) {
        Cache cache = cacheManager.getCache(cacheName);
        if (cache == null) {
          cacheManager.addCache(cacheName);
          cache = cacheManager.getCache(cacheName);
          cache.getCacheConfiguration().setEternal(true);
        }
        return cache;
      }
    
      public static CacheManager getCacheManager() {
        return cacheManager;
      }
    
    }
    
    
    これにより、ehcache全体が曖昧な量でキャッシュを削除する機能が実現される。
    締め括りをつける
    全体の過程の構想は簡単で、いくつかのAOPの知識を使って必要な機能を完成しました。しかし、特定の除去部分コードは最適化を考慮することができる。一回のキャッシュの全部の循環を通して、除去すべきキャッシュを全部きれいに除去します。今のようにいくつかのキーがあると思っているのではなく、全部のキャッシュは何回も巡回します。具体的な実現は読者に自分で完成させます。皆さんの役に立ちたいです。私たちを応援してください。