Skip to content

Repository files navigation

fluxcache

CI Coverage Maven Central License

多级缓存框架 (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

性能压测(Benchmark)

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]
Loading
指标 结果
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

页面

cache-overview.png

service-manage .png

cache-detail.png

模块

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。可参考:

1. 引入依赖(推荐)

<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 版本。

仅使用 Redisson(不引入 spring-data-redis)

<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 模块就用哪套实现,互斥依赖即可。

2. 启动类添加 @EnableFluxCaching

3. 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);
}

4. 缓存类型

  • CAFFEINE:本地缓存
  • REDIS:可移植 Redis KV(Spring Data Redis 或 Redisson Bucket)
  • REDIS_MAP:仅 Redisson RMapCache(按 entry TTL)

5. 全局配置(推荐)

先在 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 自动探测(可选)

默认关闭。开启后按 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、Prometheus flux_cache_hot_key_qps

演示缓存 hotKeyDemoCache 一级 TTL 1 秒强制过期,保证每个探测窗口都有未命中产生。

注解上未显式设置的字段(ttl <= 0initSize/maxSize <= -1fluxCacheType = NULL)会自动回落到全局配置。

6. 注解示例

一级缓存(完全使用全局 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

7. 手动注册缓存

实现 FluxCacheDataRegistered,在 registerCache 中返回 FluxMultilevelCacheCacheable 列表(示例见 example 模块)。

8. 缓存刷新

使用 @FluxRefresh(需 Redis 模块提供 FluxDistributedLock):

@FluxCacheable(
    cacheName = "studentCache",
    key = "#name",
    refresh = @FluxRefresh(
        enabled = true,
        provider = StudentMultipleKeysProvider.class,
        fixedRate = 1,
        initialDelay = 0,
        unit = TimeUnit.MINUTES,
        preheatOnStartup = true
    )
)

Dashboard

引入 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 日志提醒。也可在网关层做鉴权后将该前缀路由到内网。

可观测性(Micrometer / Prometheus / Grafana)

企业级监控不依赖内置 Dashboard,支持通过 Micrometer 将缓存指标导出到 Prometheus + Grafana,与业务指标统一治理。

1. 引入依赖

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),无需额外配置;未装配指标体系时对缓存链路零影响。

2. 指标清单

指标(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

3. Prometheus 抓取

/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

4. Grafana 面板 PromQL

# 命中率(各缓存)
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)

基准测试(Benchmark)复现

数据与图表见上文「性能压测」,本节为复现方法。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。

About

Multilevel cache for Spring Boot — Caffeine + Redisson, with annotation API and dashboard(基于 Spring Boot 的多级缓存框架,支持 Caffeine + Redisson,含 Dashboard 监控)

Topics

Resources

Stars

14 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages