首页
看点啥
插画图片
首页 看点啥 [028][缓存模块]命名缓存:多级个性化缓存配置的设计与实现

[028][缓存模块]命名缓存:多级个性化缓存配置的设计与实现

2026-07-17 0

[028][缓存模块]命名缓存:多级个性化缓存配置的设计与实现

本文章代码: gitee , gitcode , github

[028][缓存模块]命名缓存:多级个性化缓存配置的设计与实现

在复杂的业务系统中,不同缓存往往有着不同的容量、过期时间、键前缀等需求。例如,用户信息缓存可能需要较长的 TTL,而验证码缓存则只需要几分钟。传统的统一缓存配置难以满足这种差异化需求。为此,本文介绍一种“命名缓存”(Named Cache)的设计方案,允许开发者通过配置文件为每个缓存名称单独定义其策略,并同时支持 Redis 和 Caffeine 两种后端实现。

一、命名缓存的概念

命名缓存是指:在同一个缓存管理器中,根据缓存名称的不同,应用不同的缓存配置(如 TTL、是否允许空值、键前缀、初始容量等)。开发者只需在配置文件中以 caches.<缓存名称> 的方式声明参数,即可让缓存管理器在创建对应缓存时自动使用这些个性化设置。

这种设计带来以下好处:

二、整体配置模型

2.1 配置属性类

项目定义了 NamedCacheProperties 作为核心配置载体,其结构如下:

@Data
@ConfigurationProperties(prefix = "tutorials4j.cache.named")
public class NamedCacheProperties {   private NamedCacheOptions defaults = new NamedCacheOptions();  private Map caches = new HashMap<>();
}


NamedCacheOptions 定义了通用选项以及后端特有选项:

public class NamedCacheOptions {   private Duration timeToLive;  // 过期时间  private Boolean cacheNullValues;// 是否缓存null值  private Boolean enableStatistics;     // 是否启用统计
  private RedisOptions redis = new RedisOptions(); // Redis专属配置  private CaffeineOptions caffeine = new CaffeineOptions(); // Caffeine专属配置
}


其中 RedisOptions 包含 keyPrefix 键前缀;CaffeineOptions 包含 initialCapacitymaximumSizeexpireAfterAccess

每个 NamedCacheOptions 可以调用 applyDefaults(NamedCacheOptions defaults) 方法,将未设置的属性从默认配置中合并,实现“默认配置 + 差异化覆盖”的模型。

2.2 配置示例

application.yml 中:

tutorials4j:cache:  named:
defaults:
time-to-live: 60s
cache-null-values: false
redis:key-prefix: "default:"
caches:
userCache:time-to-live: 300scache-null-values: trueredis:  key-prefix: "user:"
productCache:time-to-live: 600scaffeine:  initial-capacity: 500  maximum-size: 20000


此时 userCache 会覆盖 TTL 和空值策略,并使用自己的键前缀;productCache 则使用默认 TTL 但修改 Caffeine 容量参数。

三、Redis 命名缓存的实现

3.1 缓存管理器创建器

RedisCacheManagerCreator 负责创建 RedisCacheManager 实例,采用双重检查锁单例模式保证同一配置下只有一个管理器。其 newInstance() 方法构建 RedisCacheManager.Builder 链。

public RedisCacheManager newInstance() {   RedisCacheConfiguration defaultConfig = RedisCacheConfiguration.defaultCacheConfig();  defaultConfig = RedisUtils.fillConfiguration(defaultConfig, properties.getDefaults());  RedisCacheManager.RedisCacheManagerBuilder builder = 
RedisCacheManager.builder(factory).cacheDefaults(defaultConfig);  // 应用所有 RedisCacheManagerBuilderCustomizer  redisCacheManagerBuilderCustomizer.forEach(c -> c.customize(builder));  // 应用所有 CacheManagerCustomizer  RedisCacheManager redisCacheManager = builder.build();  cacheManagerCustomizer.forEach(c -> c.customize(redisCacheManager));  return redisCacheManager;
}


3.2 命名缓存配置的注入

关键点在于 NamedRedisCacheManagerBuilderCustomizer,它实现了 RedisCacheManagerBuilderCustomizer 接口,会在 builder 构建前被调用。该类遍历 properties.getCaches() 为每个命名缓存创建独立的 RedisCacheConfiguration,然后通过 builder.withInitialCacheConfigurations(configMap) 一次性注入。

@Override
public void customize(RedisCacheManager.RedisCacheManagerBuilder builder) {   RedisCacheConfiguration defaultConfig = builder.cacheDefaults();  Map configMap = new HashMap<>();  properties.getCaches().forEach((name, options) -> { 
RedisCacheConfiguration namedConfig = RedisUtils.fillConfiguration(defaultConfig, options);
configMap.put(name, namedConfig);  });  builder.withInitialCacheConfigurations(configMap);
}


RedisUtils.fillConfiguration 方法根据 NamedCacheOptions 中的 timeToLivecacheNullValueskeyPrefix(通过 RedisOptions)修改默认配置。这样,当应用第一次操作 userCache 时,RedisCacheManager 就会使用该缓存专属的配置。

3.3 自动装配

CacheRedisConfiguration 中条件化地注册了上述定制器和创建器:

@Bean(CacheManagerCreatorCategory.REDIS_CREATOR)
@ConditionalOnMissingBean
RedisCacheManagerCreator redisCacheManagerCreator(...) {  ... }


并同时注册了 JSON 序列化定制器等(与命名缓存主题无关的略述)。

四、Caffeine 命名缓存的实现

Caffeine 是进程内缓存,其命名缓存实现思路与 Redis 类似,但需要直接控制 CaffeineCacheManager 的缓存创建逻辑。

4.1 自定义缓存管理器

FlexibleCaffeineCacheManager 继承自 CaffeineCacheManager,重写了 createNativeCaffeineCache(String name) 方法:

@Override
protected Cache createNativeCaffeineCache(String name) {   Map optionsMap = properties.getCaches();  if (optionsMap.containsKey(name)) { 
NamedCacheOptions options = optionsMap.get(name);
options.applyDefaults(properties.getDefaults());  // 合并默认配置
Caffeine caffeine = Caffeine.newBuilder();
CaffeineUtils.copyOption(caffeine, options);// 应用 TTL、容量等
return caffeine.build();  }  return super.createNativeCaffeineCache(name);
}


关键步骤:

  1. 根据缓存名称查找是否有专用配置。
  2. 调用 applyDefaults 将未设置的属性从全局默认值中补全。
  3. 创建一个新的 Caffeine 构造器,通过 CaffeineUtils.copyOption 设置过期、容量、访问过期等参数。
  4. 调用 build() 生成原生 Cache 实例。

这样,每个命名缓存都会拥有独立的 Caffeine 对象,其大小、过期策略互不干扰。

4.2 缓存管理器创建器

CaffeineCacheManagerCreator 同样采用单例模式,它的 newInstance() 直接创建 FlexibleCaffeineCacheManager 并注入全局 Caffeine 实例(该实例基于 properties.getDefaults() 构建,作为后备默认值)。

public CaffeineCacheManager newInstance() {   FlexibleCaffeineCacheManager caffeineCacheManager = new FlexibleCaffeineCacheManager(properties);  caffeineCacheManager.setCaffeine(caffeine);  return caffeineCacheManager;
}


4.3 自动装配

CacheCaffeineConfiguration 负责创建默认 Caffeine Bean 和 CaffeineCacheManagerCreator Bean。同时,FlexibleCaffeineCacheManager 内部已处理命名缓存的配置,因此无需额外的 CacheManagerCustomizer

五、使用示例

假设我们有一个业务服务,需要同时使用 Redis 缓存用户信息,使用 Caffeine 缓存产品目录:

@Service
public class UserService {   @Cacheable(value = "userCache", key = "#userId")  public User getUser(Long userId) {  ... }
}

@Service
public class ProductService {   @Cacheable(value = "productCache", key = "#productId")  public Product getProduct(Long productId) {  ... }
}


配置文件(application.yml)如下:

tutorials4j.cache.named:defaults:  time-to-live: 60s  cache-null-values: false  redis:
key-prefix: "global:"caches:  userCache:
time-to-live: 300s
cache-null-values: true
redis.key-prefix: "user:"  productCache:
time-to-live: 600s
caffeine:
initial-capacity: 200
maximum-size: 10000
expire-after-access: 300s


运行时:

开发者只需关注 @Cacheable 注解中的缓存名称,底层管理器会自动应用对应策略。

六、总结

命名缓存机制通过统一的配置模型将缓存名称与具体参数解耦,极大地提升了缓存管理的灵活性和可维护性。本文分别以 Redis 和 Caffeine 为例,展示了:

这种设计可以轻松扩展至其他缓存提供者(如 EhCache),核心思想始终不变:让配置跟随缓存名称动态变化,而非全局僵化。在微服务或多业务模块的架构中,命名缓存是一项值得参考的基础设施实践。

喜欢(0)

上一篇

大模型GPU推理队列排队治理:限流规则+优先级调度+长短拆分+集群负载指引.172

大模型GPU推理队列排队治理:限流规则+优先级调度+长短拆分+集群负载指引.172

下一篇

小红书主站网页入口官方链接-小红书官方主页一键进入

小红书主站网页入口官方链接-小红书官方主页一键进入
猜你喜欢