适配网点/用户低频数据:同步加载+定时刷新+缓存预热一站式实现
在企业级微服务开发中,网点基础资料、用户信息这类数据具备访问频率高、变更频率低的核心特点。若每次请求都直接查询数据库,会产生大量无效IO,严重降低接口响应速度。本文基于Caffeine Cache(Java 性能最强本地缓存框架) ,实现一套同步加载、定时刷新、服务预热的本地缓存方案,零侵入、高性能解决低频静态数据缓存问题。
一、需求背景
-
缓存对象:网点基础资料、用户信息等不常变更的业务基础数据;
-
核心目标:减少数据库查询压力,提升接口响应性能;
-
功能要求:
- 服务启动时自动预热缓存,避免首次请求卡顿;
- 定时自动刷新缓存,保证数据最终一致性;
- 支持缓存淘汰监控,方便问题排查;
- 纯内存操作,无第三方中间件依赖。
二、方案选型
1. 为什么选择 Caffeine Cache?
- 性能极致:读写性能远超 Guava Cache、Ehcache,为 Java 生态本地缓存天花板;
- 策略丰富:支持过期淘汰、异步刷新、容量限制、淘汰监听等企业级特性;
- Spring 无缝集成:完美适配 Spring Boot,支持依赖注入、定时任务;
- 轻量无依赖:纯内存缓存,无需部署额外服务,开箱即用。
2. 本方案核心架构
采用 同步加载 + 被动异步刷新 + 定时主动刷新 + 服务启动预热 组合策略:
- 同步加载:缓存未命中时,同步加载数据源并自动缓存;
- 异步刷新:访问缓存时自动后台刷新,不阻塞业务请求;
- 定时刷新:每小时主动强制刷新所有缓存,解决冷数据不更新问题;
- 缓存预热:服务启动完成后提前加载所有核心数据。
三、环境搭建
1. Maven 核心依赖
Spring Boot 项目只需引入两个依赖,无需手动管理版本:
<!-- Spring 缓存 Starter(自动整合Caffeine) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- Caffeine 本地缓存核心依赖 -->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
2. 启动类开启核心注解
在 Spring Boot 启动类添加注解,开启缓存和定时任务功能:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching // 开启Spring缓存功能
public class OmsApp {
public static void main(String[] args) {
SpringApplication.run(OmsApp.class, args);
}
}
四、核心代码实现
1. 缓存键枚举管理(统一维护)
通过枚举类统一管理所有缓存 Key,避免硬编码,方便后期扩展维护:
package com.xm.kite.caffeineCache;
import java.util.ArrayList;
import java.util.List;
/**
* 缓存Key枚举
* 统一管理网点、用户等本地缓存键值
*/
public enum CacheEnum {
CACHEDEPTS("CACHEDEPTS", "网点基础资料", ""),
CACHEUSERS("CACHEUSERS", "用户资料", "");
// 缓存唯一Key
private final String key;
// 缓存名称
private final String cacheName;
// 缓存描述
private final String cacheDesc;
CacheEnum(String key, String cacheName, String cacheDesc) {
this.key = key;
this.cacheName = cacheName;
this.cacheDesc = cacheDesc;
}
public String getKey() {
return key;
}
/**
* 获取所有缓存Key
*/
public static List<String> getAllKeys() {
List<String> keys = new ArrayList<>();
for (CacheEnum cacheEnum : CacheEnum.values()) {
keys.add(cacheEnum.getKey());
}
return keys;
}
/**
* 根据Key匹配枚举
*/
public static CacheEnum getByKey(String key) {
if (key == null) {
return null;
}
for (CacheEnum cacheEnum : CacheEnum.values()) {
if (cacheEnum.getKey().equals(key)) {
return cacheEnum;
}
}
return null;
}
}
2. Caffeine 核心配置类
实现缓存构建、同步加载、定时刷新、缓存预热、淘汰监听全套企业级功能:
package com.xm.kite.caffeineCache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;
import java.util.concurrent.TimeUnit;
/**
* Caffeine 本地缓存核心配置
* 同步加载 + 定时主动刷新 + 服务预热 + 淘汰监控
*/
@Slf4j
@Configuration
public class CaffeineConfig {
/**
* 构建LoadingCache同步缓存Bean
* 支持自动加载、异步刷新、过期淘汰
*/
@Bean
@Qualifier("caffeineCache")
public LoadingCache<String, Object> caffeineCache() {
return Caffeine.newBuilder()
// 初始容量:预分配内存,提升性能
.initialCapacity(100)
// 最大缓存条数:防止内存溢出
.maximumSize(200)
// 兜底过期:写入3小时后强制删除缓存
.expireAfterWrite(3, TimeUnit.HOURS)
// 异步刷新:2小时后访问时自动后台刷新(不阻塞)
.refreshAfterWrite(2, TimeUnit.HOURS)
// 缓存淘汰监听器:监控缓存删除原因
.evictionListener((key, value, cause) -> {
log.info("【Caffeine缓存淘汰】key={}, 原因={}", key, cause);
})
// 同步加载器:缓存未命中/刷新时加载数据源
.build(this::loadUserFromDatabase);
}
/**
* 注入缓存Bean
*/
@Resource
@Qualifier("caffeineCache")
private LoadingCache<String, Object> caffeineCacheBean;
/**
* 定时主动刷新缓存
* cron:每小时整点执行
* 作用:解决冷数据不触发refreshAfterWrite的问题
*/
@Scheduled(cron = "0 0 * * * ?")
public void autoRefreshCache() {
log.info("【Caffeine】开始每小时定时刷新缓存");
CacheEnum.getAllKeys().forEach(caffeineCacheBean::refresh);
log.info("【Caffeine】定时缓存刷新完成");
}
/**
* 同步加载数据源
* 实际业务中替换为数据库/RPC查询逻辑
*/
public Object loadUserFromDatabase(String key) {
CacheEnum cacheEnum = CacheEnum.getByKey(key);
if (cacheEnum == null) {
return "未知缓存数据:" + key;
}
// 业务数据加载(可替换为真实查询)
return switch (cacheEnum) {
case CACHEDEPTS -> "网点基础资料数据";
case CACHEUSERS -> "用户信息数据";
};
}
/**
* 服务启动缓存预热
* @PostConstruct:Bean初始化完成后执行
*/
@PostConstruct
public void warmUpCache() {
log.info("【Caffeine】服务启动,开始缓存预热");
CacheEnum.getAllKeys().forEach(key -> {
Object cacheData = caffeineCacheBean.get(key);
log.info("【Caffeine】缓存预热成功 key={}, data={}", key, cacheData);
});
}
}
五、核心功能详解
1. 同步加载机制
使用 LoadingCache 同步缓存,调用 get(key) 时:
- 缓存存在 → 直接返回数据;
- 缓存不存在 → 自动执行
loadUserFromDatabase加载数据并缓存; - 保证数据强一致性,适合本地基础数据缓存。
2. 双缓存刷新策略
- 被动异步刷新(
refreshAfterWrite)
- 缓存写入2小时后,访问时后台异步加载新数据,不阻塞业务请求;
- 主动定时刷新(
@Scheduled)
- 每小时主动调用
refresh(key)强制刷新所有缓存,解决冷数据不更新问题。
3. 兜底过期保护
expireAfterWrite(3, TimeUnit.HOURS):
缓存写入3小时后强制删除,防止缓存数据永久不更新,保证数据最终一致性。
4. 缓存淘汰监听
实时监控缓存删除行为,打印淘汰原因:
EXPIRED:缓存过期;REPLACED:缓存被覆盖/刷新;SIZE:超出最大容量;EXPLICIT:手动删除。
5. 服务启动预热
通过 @PostConstruct 注解,服务启动完成后自动加载所有缓存数据,彻底避免首次请求卡顿。
六、业务代码使用示例
在 Service 层注入缓存 Bean,直接使用缓存数据:
import com.github.benmanes.caffeine.cache.LoadingCache;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class BaseDataService {
@Resource
@Qualifier("caffeineCache")
private LoadingCache<String, Object> caffeineCache;
/**
* 获取网点基础资料(走本地缓存)
*/
public Object getDeptData() {
return caffeineCache.get(CacheEnum.CACHEDEPTS.getKey());
}
/**
* 获取用户信息(走本地缓存)
*/
public Object getUserData() {
return caffeineCache.get(CacheEnum.CACHEUSERS.getKey());
}
}
七、方案优势总结
- 高性能:纯内存操作,无网络开销,接口响应速度提升 90% 以上;
- 高可用:双刷新策略+兜底过期,兼顾性能与数据一致性;
- 易维护:枚举统一管理缓存键,日志监控全覆盖;
- 零侵入:无需修改业务核心逻辑,配置化实现缓存;
- 防雪崩:无全量清空缓存操作,避免数据库压力暴增。
八、适用场景
- 低频变更、高频访问的基础数据(网点、用户、字典、枚举);
- 无需分布式共享的单机本地缓存;
- 追求极致性能、低延迟的企业级接口。
九、总结
本文基于 Caffeine Cache 实现了一套生产级本地缓存解决方案,针对网点、用户信息等低频静态数据,通过同步加载、被动异步刷新、主动定时刷新、服务启动预热四大核心能力,完美解决了数据库查询性能瓶颈。
方案轻量、高效、易落地,是 Spring Boot 项目中本地缓存的最佳实践,可直接复用至物流、电商、ERP 等各类企业业务系统。