多级缓存框架 (multilevel cache framework)
A lightweight multilevel cache framework for Spring Boot applications. Supports Caffeine L1 and Redis L2 cache with cache penetration/breakdown/avalanche protection, distributed cache invalidation via Pub/Sub, single-flight cache loading, and a built-in cache management dashboard. Annotate-based usage, compatible with Spring Data Redis and Redisson.
- 自定义一级 / 二级缓存
- 支持 Caffeine 分布式删除、更新(基于 Redis Pub/Sub)
- 支持解决缓存雪崩(随机过期时间)
- 支持缓存穿透(缓存 null)
- 支持缓存击穿防护(单飞 single-flight:同一 key 并发未命中仅一个线程加载,其余线程复用结果)
- Dashboard 操作缓存元数据 / 清空 / 按 key 查询与清理
- Dashboard 缓存命中率等监控统计
- 纯注解使用
- 多 Redis 客户端:默认 Spring Data Redis;Redisson 可选独立模块(含
REDIS_MAP/ RMapCache) - Micrometer 指标导出(可选模块):
flux_cache_hit_total/flux_cache_miss_total/flux_cache_load_time等,对接 Prometheus + Grafana - 热 Key 自动探测:按 key 维度滑动窗口统计 QPS/未命中,双阈值 + 连续窗口确认,支持日志 / Prometheus gauge / Dashboard 查询(
/cache/manager/v1/hot-keys)
JMH 基准(fluxcache-benchmark,M2 Max / JDK21 / JMH 1.37),对比 FluxCache vs 纯 Redis vs Spring Cache + Caffeine vs JetCache:
xychart-beta
title "读延迟对比(µs/op,对数刻度)"
x-axis ["FluxCache L1(注解)", "FluxCache L1(直调)", "Spring Cache+Caffeine", "JetCache", "纯Redis", "FluxCache L2"]
y-axis "µs/op" 0 --> 2600
bar [0.385, 0.038, 0.019, 0.170, 2475.245, 2585.417]
| 指标 | 结果 |
|---|---|
| L1 命中延迟(完整注解链路) | 0.385 µs,相对纯 Redis(2.475 ms)快 ~6,400x |
| 90% L1 / 10% L2 混合读吞吐 | 31,494 ops/s,纯 Redis 全远程仅 2,808 ops/s,高 11.2x |
| 并发击穿(16 线程同一冷 key) | 单飞开启吞吐 9,180 ops/s vs 关闭 1,609 ops/s,高 5.7x |
| 击穿 → DB 调用 | 单飞开启 0.042 次/op vs 关闭 1.43 次/op,减少约 34x |
| 框架成本(L2 命中相对纯 Redis) | 仅 +4.4% |
方法:纯 Redis 基线以 2 ms 固定延迟模拟同城/局域网 RTT(结果随真实 RTT 线性变化);FluxCache 一律走完整注解链路(SpEL + 拦截器 + 单飞 + 监控 + 多级缓存),即生产真实路径。完整报告见 BENCHMARK-REPORT.md。
fluxcache
├── fluxcache-core 核心引擎与抽象(无 Redis 客户端依赖)
├── flux-cache-spring-boot-starter/ Spring Boot Starter 父模块
│ ├── fluxcache-redis-spring Spring Data Redis 实现(REDIS)
│ ├── fluxcache-redis-redisson Redisson 实现(REDIS + REDIS_MAP),不依赖 spring-data-redis
│ ├── fluxcache-admin Dashboard REST
│ └── fluxcache-all-spring-boot-starter 默认入口:redis-spring + admin
└── fluxcache-example/ 示例项目
目前仅支持 Spring Boot。可参考:
<dependency>
<groupId>io.github.weihubeats</groupId>
<artifactId>fluxcache-all-spring-boot-starter</artifactId>
<version>0.0.4</version>
</dependency>默认包含 Spring Data Redis 实现与 admin。应用需提供 RedisConnectionFactory(Boot 自动配置或自行声明)。
Spring Boot 3 请使用 spring-boot-3.x 分支上的 3.0.0 版本。
<dependency>
<groupId>io.github.weihubeats</groupId>
<artifactId>fluxcache-redis-redisson</artifactId>
<version>0.0.4</version>
</dependency>
<dependency>
<groupId>io.github.weihubeats</groupId>
<artifactId>fluxcache-admin</artifactId>
<version>0.0.4</version>
</dependency>并提供 RedissonClient Bean。引入哪个 Redis 模块就用哪套实现,互斥依赖即可。
Starter / Spring Data Redis:
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(new RedisStandaloneConfiguration("127.0.0.1", 6379));
}Redisson:
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
config.setCodec(new JsonJacksonCodec(new ObjectMapper().registerModule(new JavaTimeModule())));
return Redisson.create(config);
}CAFFEINE:本地缓存REDIS:可移植 Redis KV(Spring Data Redis 或 Redisson Bucket)REDIS_MAP:仅 RedissonRMapCache(按 entry TTL)
先在 application.yml 中配置一级/二级缓存默认值,大幅减少每个注解上的重复配置:
flux:
cache:
first-cache:
ttl: 5
time-unit: MINUTES
cache-type: CAFFEINE
init-size: 20
max-size: 2000
secondary-cache:
ttl: 5
time-unit: MINUTES
cache-type: REDIS
default-cache-level: FirstCacheable默认关闭。开启后按 key 统计读 QPS 与未命中,双条件(QPS 且未命中数)连续多个分片命中才上报,并对通知做冷却节流:
flux:
cache:
hot-key:
enabled: true
window-seconds: 60 # 判定滑动窗口长度(秒)
slot-seconds: 10 # 窗口分片(秒)
hot-qps-threshold: 10.0 # 窗口读 QPS 阈值
hot-miss-threshold: 5 # 窗口最小未命中次数(穿透敏感)
confirm-ticks: 2 # 连续多少个分片判定热才上报(消抖)
max-hot-key-capacity: 200000 # 统计表上限,超限按 FIFO 淘汰
notify-interval-ms: 30000 # 热期间重复通知冷却间隔热 key 输出:INFO 日志、Prometheus gauge flux_cache_hot_key_qps(标签 cache/key,需引入 fluxcache-metrics)、Dashboard GET /cache/manager/v1/hot-keys。自定义监听实现 FluxHotKeyListener Bean 即可自动接入。
示例演示: fluxcache-example-starter 内置热 key 演示(阈值已调低便于快速观测):
GET /hot-key/pressure?seconds=10&qps=500&name=hotKey-001:模拟热点流量,按固定 QPS 持续打压单个 key,返回请求总数与热 key 判定结果GET /hot-keys:查看当前热 key 快照(命中/未命中/QPS/命中率/热状态)- Dashboard
GET /cache/manager/v1/hot-keys、Prometheusflux_cache_hot_key_qps
演示缓存 hotKeyDemoCache 一级 TTL 1 秒强制过期,保证每个探测窗口都有未命中产生。
注解上未显式设置的字段(ttl <= 0、initSize/maxSize <= -1、fluxCacheType = NULL)会自动回落到全局配置。
一级缓存(完全使用全局 Caffeine 默认值):
@FluxCacheable(cacheName = "firstCacheByCaffeine", key = "#name")
public List<StudentVO> firstCacheByCaffeine(String name) {
return mockSelectSql();
}一级 Redis(仅覆盖缓存类型与 TTL):
@FluxCacheable(cacheName = "studentRedis", key = "#name",
firstCacheable = @FirstCacheable(fluxCacheType = FluxCacheType.REDIS, ttl = 5L))
public List<StudentVO> firstCacheByRedis(String name) {
return mockSelectSql();
}二级缓存 Caffeine + Redis(仅覆盖 TTL,其余走全局):
@FluxCacheable(cacheName = "studentLocalRedis", key = "#name",
firstCacheable = @FirstCacheable(ttl = 1L),
secondaryCacheable = @SecondaryCacheable(enabled = true, ttl = 3L))
public List<StudentVO> secondaryCacheByCaffeineRedis(String name) {
return mockSelectSql();
}二级缓存通过
secondaryCacheable.enabled = true自动推断,无需显式声明fluxCacheLevel。
实现 FluxCacheDataRegistered,在 registerCache 中返回 FluxMultilevelCacheCacheable 列表(示例见 example 模块)。
使用 @FluxRefresh(需 Redis 模块提供 FluxDistributedLock):
@FluxCacheable(
cacheName = "studentCache",
key = "#name",
refresh = @FluxRefresh(
enabled = true,
provider = StudentMultipleKeysProvider.class,
fixedRate = 1,
initialDelay = 0,
unit = TimeUnit.MINUTES,
preheatOnStartup = true
)
)引入 starter(含 admin)后访问管理端能力;前端见 fluxcache-dashboard
Dashboard 包含清空/驱逐缓存等破坏性操作,生产环境务必配置鉴权:
flux:
cache:
admin:
enabled: true # 默认 true;置 false 完全关闭 Dashboard REST
token: your-secret # 非空时所有请求需携带请求头 X-Flux-Cache-Token: your-secret
# prefix: /cache/manager/v1 # 自定义路径前缀未配置 token 时启动会输出 WARN 日志提醒。也可在网关层做鉴权后将该前缀路由到内网。
企业级监控不依赖内置 Dashboard,支持通过 Micrometer 将缓存指标导出到 Prometheus + Grafana,与业务指标统一治理。
fluxcache-metrics 已传递依赖 actuator 与 Prometheus registry,只需 2 个依赖:
<dependency>
<groupId>io.github.weihubeats</groupId>
<artifactId>fluxcache-all-spring-boot-starter</artifactId>
<version>0.0.4</version>
</dependency>
<dependency>
<groupId>io.github.weihubeats</groupId>
<artifactId>fluxcache-metrics</artifactId>
<version>0.0.4</version>
</dependency>应用装配 MeterRegistry 后自动生效(@ConditionalOnBean),无需额外配置;未装配指标体系时对缓存链路零影响。
| 指标(Prometheus 名) | 类型 | 说明 | 标签 |
|---|---|---|---|
flux_cache_hit_total |
Counter | 命中累计 | cache |
flux_cache_miss_total |
Counter | 未命中累计 | cache |
flux_cache_eviction_total |
Counter | 驱逐累计 | cache |
flux_cache_load_time_seconds |
Summary/Histogram | L2/DB 加载耗时,含 p50/p95/p99 | cache |
flux_cache_hit_rate |
Gauge | 命中率 = hit/(hit+miss) | cache |
flux_cache_miss_rate |
Gauge | 未命中率 = miss/(hit+miss) | cache |
完整对接指南(Prometheus 抓取配置、Grafana 数据源/面板导入、告警规则)见 docs/observability/prometheus-grafana.md,含可直接导入的 fluxcache-dashboard.json 与告警规则 alerts.yml。
/actuator/prometheus 端点直接暴露:
# TYPE flux_cache_hit_total counter
flux_cache_hit_total{cache="studentLocalRedis"} 12345
# TYPE flux_cache_load_time_seconds summary
flux_cache_load_time_seconds{quantile="0.95",cache="studentLocalRedis"} 0.00042
# 命中率(各缓存)
sum(rate(flux_cache_hit_total[5m])) by (cache)
/ (sum(rate(flux_cache_hit_total[5m])) by (cache) + sum(rate(flux_cache_miss_total[5m])) by (cache))
# P99 加载耗时
histogram_quantile(0.99, sum(rate(flux_cache_load_time_seconds_bucket[5m])) by (le))
# 缓存读取 QPS
sum(rate(flux_cache_hit_total[5m]) + rate(flux_cache_miss_total[5m])) by (cache)
数据与图表见上文「性能压测」,本节为复现方法。fluxcache-benchmark 基于 JMH,默认不参与构建,需激活 profile:
# 方式一:直接运行脚本(编译 + 生成 JSON 结果到 docs/benchmark/)
./fluxcache-benchmark/run-benchmark.sh
# 方式二:仅构建,手动指定类与参数
mvn clean package -Pbenchmark -Dgpg.skip=true
java -jar fluxcache-benchmark/target/benchmarks.jar FluxCacheLatencyBenchmark -rf json主要场景:
FluxCacheThroughputBenchmark:FluxCache vs Spring Caffeine 本地缓存吞吐FluxCacheLatencyBenchmark:FluxCache(含 L1/L2)vs 纯 Redis vs Spring Caffeine vs JetCache 延迟对比SingleFlightPenetrationBenchmark:并发缓存穿透时开启/关闭单飞的命中与耗时对比
产物:docs/benchmark/results.json(JMH 原始结构化数据)、docs/benchmark/run.log(完整日志)。完整报告见 docs/benchmark/BENCHMARK-REPORT.md。
CI(mvn verify)内置 JaCoCo 覆盖率检查:fluxcache-core 行覆盖率 ≥ 85%、分支覆盖率 ≥ 85%,不达标构建失败。覆盖率报告见 fluxcache-core/target/site/jacoco/,并上报 Codecov。


