一、前言

  1. 近期被刷接口了,思考减少 本地缓存进步性能,另配置 限流
  2. 应用 spring-cache 注解式缓存,能够进步应用缓存的开发效率
  3. 不同业务,能够定制 本人的缓存策略,是根本需要
  4. 多模块我的项目,最好在 对立的模块(如 common) 加载缓存配置

二、计划

1. 配置缓存:接口 + 枚举 + Lombok

缓存配置接口:

public interface ICacheConfig {    Integer getTtl();}

common模块缓存配置(应用 Lombok 的 FieldNameConstants 主动生成 常量):

@lombok.Getter@lombok.AllArgsConstructor@lombok.experimental.FieldNameConstants(onlyExplicitlyIncluded = true)public enum CommonCacheConfig implements ICacheConfig {    @FieldNameConstants.Include QUOTE_LEVEL(1000, 2);    private final Integer ttl;}

业务模块缓存配置:

@lombok.Getter@lombok.AllArgsConstructor@lombok.experimental.FieldNameConstants(onlyExplicitlyIncluded = true)public enum QuoteServiceCacheConfig implements ICacheConfig {    @FieldNameConstants.Include HOT_STOCK(1000, 30);    private final Integer ttl;}

2. 多模块配置加载:Reflections + SimpleCacheManager

  • 通过 Reflections 库加载多模块配置
  • SimpleCacheManager 组合 各种不同配置的 缓存

    @EnableCaching@Configurationpublic class CacheConfig {  private Logger log = LoggerFactory.getLogger(this.getClass());  @Bean  @Primary  public CacheManager cacheManager() {      final SimpleCacheManager cacheManager = new SimpleCacheManager();      final String prefix = "package";
        Set<Class<? extends ICacheConfig>> classes = new Reflections(prefix).getSubTypesOf(ICacheConfig.class);        log.info("cache types|{}|{}", prefix, classes);        List<Cache> caches = classes.stream().flatMap(clazz -> Arrays.stream(clazz.getEnumConstants())).map(config -> {            final Caffeine<Object, Object> cache = Caffeine.newBuilder().recordStats();            Optional.ofNullable(config.getTtl()).ifPresent(t -> cache.expireAfterWrite(t, TimeUnit.SECONDS));            return new CaffeineCache(((Enum) config).name(), cache.build());        }).collect(Collectors.toList());        cacheManager.setCaches(caches);        return cacheManager;    }

3. 应用缓存

  • 应用 @Cacheable(cacheNames = CommonCacheConfig.Fields.QUOTE_LEVEL, sync = true) 操作缓存
  • 应用 Lombok 的 FieldNameConstants 主动生成的 常量:

    public enum CommonCacheConfig implements ICacheConfig {  public static final class Fields {      public static final String QUOTE_LEVEL = "QUOTE_LEVEL";  }}

三、总结

  • 通过 接口 + 枚举,业务模块不必改common模块, 新增枚举 就能 不便的配置、应用缓存,合乎 开闭准则
  • 通过 Lombok 的 FieldNameConstants 主动生成 枚举名称常量,便于代码 导航、重构
  • 通过 Reflections 库,common模块主动加载 各模块的缓存配置,SimpleCacheManager 组合 各种不同配置的 缓存(CaffeineCacheManager 不能),升高应用老本,进步可维护性
  • sync = true,加锁,只有一个线程去加载数据,其余线程阻塞,避免 缓存击穿
  • alibaba/jetcache:反对TTL和两级缓存、主动刷新和加载爱护 等
  • netease-im/camellia:网易开源,有意思的是 反对基于注解执行mget,mevict等批量操作

本文首先公布于 https://www.890808.xyz/ ,其余平台须要审核更新慢一些。


5