ehcache Fuzzy Batch Removal Method for Caches

  • 2021-01-22 05:06:49
  • OfStack

preface

As we all know, encache is the most popular java open source caching framework, simple configuration, clear structure, powerful. The annotation @Cacheable allows you to quickly add method results to the cache. A specified cache can be cleared quickly with @CacheEvict.

However, since the @CacheEvict annotation is ES10en-ES11en and does not support fuzzy deletion, you run into problems. When I use @Cacheable with Spring and EL expressions to add multiple caches of the same 1 method, for example:


@GetMapping("/listOfTask/{page}/")
@Cacheable(value = "BusinessCache", key = "'listOfTask_'+ #page")
public ResponseMessage<PageTaskVO> getTaskList(@PathVariable("page") String page) {
  do something...
}

The above code is paging to get task information. The page in the argument is obtained with the EL expression and added to the ehcache cache using @Cacheable as the cached key. At this point, key of type listOfTask_1, listOfTask_2, listOfTask_3 will appear in the cache.

The list changes as tasks are added or removed. At this point, the cache associated with listOfTask_* needs to be completely removed. At this point, I don't know how many listOfTask_* related items are in the cache, so it's impossible to delete them all by calling @CacheEvict.

Since ES34en itself cannot support it, it is up to us to implement it.

implementation

Given the cache added by the annotations used, removing the cache also uses the annotation processing to maintain the uniformity of the development. Annotations are also developer-friendly. Let's consider using custom annotations to obfuscate bulk removal caches.

First, define the annotation CacheRemove:


@Target({ java.lang.annotation.ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface CacheRemove {
  String value();
  String[] key();
}

Where, value, like ehcache 1, is used to define the cache name to be operated on. key is an array that holds a variety of cached key regular expressions. The name CacheRemove is clear and understandable, and does not conflict with the annotations of ehcache itself. This is the end of the definition of annotations. Next, you need to deal with the annotations, and because of the spring framework, it's natural to think of AOP as a concrete implementation of the annotations.

The purpose of the annotation is to obfuscate cache removal in bulk. The following two issues need to be considered:

In what way does the fuzzy match work How to delete key in batch

And the way I'm going to do it, which I think is the easiest way to do it, is this:

In what way does fuzzy match - key in CacheRemove pass regular, can pass multiple, use regular match How to delete key in batch - - Loop through all key, find match regular delete

First define the class name CacheRemoveAspect:


@Aspect
@Component
public class CacheRemoveAspect {
  @Pointcut(value = "(execution(* *.*(..)) && @annotation(com.example.CacheRemove))")
  private void pointcut() {}

  do something...
}

Define pointcuts in the section, using execution(* *.*(..)) & & annotation(com.example.CacheRemove)) means that all annotated classes CacheRemove are executed, and the value in @annotation is the fully qualified name of the annotation.

Now that the pointcut is defined, the most important thing is to implement the facets. Generally speaking, the cache will not be removed until the add/delete method has been executed. So use @AfterReturning () to implement it. The following things need to be done in the concrete implementation:

Comments on intercepting methods Verify that the annotation is CacheRemove Since the key passed in by the annotation is an array, loop through each key Compile each key in the loop as pattern and loop through all caches, removing the caches on the match

The specific implementation is as follows:


@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(); // Regular to be removed 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);
        }
      }
    }
  }
}

The above is the specific implementation of fuzzy batch cache removal for ehcache. BusinessCacheUtils is its own encapsulated ehcache tool class. The main implementation of access to the cache pool, access to the cache, remove the cache, add cache, view all the cache and other normal functions. The code is as follows:


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();
  }

  /**
   *  To obtain 1 a Cache If not, create 1 A. 
   * @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;
  }

}

At this point, the whole ehcache fuzzy batch cache removal function is realized.

conclusion


Related articles: