一、前言
- 近期被刷接口了,考慮增加 本地緩存提高性能,另配置 限流
- 使用 spring-cache 注解式緩存,可以提高使用緩存的開發(fā)效率
- 不同業(yè)務(wù),可以定制 自己的緩存策略,是基本需求
- 多模塊項目,最好在 統(tǒng)一的模塊(如 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;
}
業(yè)務(wù)模塊緩存配置:
@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
@Configuration
public 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";
}
}
三、總結(jié)
- 通過 接口 + 枚舉,業(yè)務(wù)模塊不用改common模塊, 新增枚舉 就能 方便的配置、使用緩存,符合 開閉原則
- 通過 Lombok 的 FieldNameConstants 自動生成 枚舉名稱常量,便于代碼 導(dǎo)航、重構(gòu)
- 通過 Reflections 庫,common模塊自動加載 各模塊的緩存配置,SimpleCacheManager 組合 各種不同配置的 緩存(CaffeineCacheManager 不能),降低使用成本,提高可維護性
- sync = true,加鎖,只有一個線程去加載數(shù)據(jù),其他線程阻塞,防止 緩存擊穿
- alibaba/jetcache:支持TTL和兩級緩存、自動刷新和加載保護 等
- netease-im/camellia:網(wǎng)易開源,有意思的是 支持基于注解執(zhí)行mget,mevict等批量操作