第3章:缓存抽象层的整体架构蓝图——分层模型、模块划分与组件依赖

3.1 架构边界与上下文

缓存抽象层位于业务系统与具体缓存中间件之间,其核心使命是将缓存操作与底层实现解耦。本章定义的边界如下:

  • 上边界:业务代码通过统一 API 读写缓存,不感知后端是 Redis、Memcached 还是本地堆缓存。
  • 下边界:抽象层对接具体缓存客户端(如 Jedis、Redisson、Memcached client),通过适配器模式屏蔽差异。
  • 侧边界:与配置中心、监控系统、序列化组件通过 SPI 或依赖注入集成,不直接硬编码。
架构约束: 抽象层内部不允许出现业务逻辑判断,所有缓存策略(TTL、备用、降级)必须在策略层声明,不得渗透到接口层。

3.2 三层分层模型

缓存抽象层采用严格的三层垂直划分,每层各司其职,依赖方向自顶向下:

层次核心职责典型模块对外依赖
接口层暴露稳定 API 给业务方;定义缓存操作契约CacheClient、@Cacheable 注解解析器、批量操作接口不依赖任何下层实现
策略层管理缓存策略(TTL、淘汰、降级、备份);路由请求到合适的实现CachePolicyManager、FallbackRouter、CacheKeyBuilder依赖接口层定义的接口
实现层封装具体缓存中间件;提供连接池、序列化、故障转移RedisAdapter、LocalCacheAdapter、CompositeCacheAdapter依赖策略层定义的策略配置
设计观点: 策略层是分层模型中最关键的“胶水”层——它决定了缓存行为(如热点数据是否自动备份到本地),而实现层只关心如何存取。

3.3 组件依赖关系图

下图展示了缓存抽象层内主要模块的依赖与协作关系。注意箭头方向表示“依赖或调用”:

缓存抽象层分层依赖关系 @Cacheable 注解解析 CacheClient 统一接口 批量操作 CacheMulti 接口层 CachePolicyManager FallbackRouter CacheKeyBuilder 策略层 RedisAdapter LocalCacheAdapter CompositeCacheAdapter 实现层 配置策略注入 说明 • 实线箭头表示调用依赖:接口层调用策略层,策略层调用实现层。 • 橙色虚线箭头表示配置反馈:实现层通过 SPI 向策略层注册能力,策略层据此调整行为。 • 同一层内的模块可互相调用(如 FallbackRouter 依赖 CachePolicyManager 判断是否降级)。 — 上边界(业务代码) — — 下边界(缓存中间件) —

3.4 数据流与控制流

一次典型的缓存写入请求经过以下路径:

  1. 接口层接收 set(key, value, ttl),将其包装为 CacheWriteRequest 上下文对象。
  2. 策略层的 CachePolicyManager 根据 key 的配置决定写入策略(如是否同步写本地+远程、是否压缩)。
  3. 实现层的 RedisAdapter 或 LocalCacheAdapter 执行真正存储,并返回结果。
  4. 结果按原路返回,策略层可将结果写入监控指标。

控制流中最重要的信任链路在于:策略层信任接口层传入的 key 合法性(格式校验已在接口层完成),实现层信任策略层下发的配置(如连接超时等)。任何跨层信任违规都应通过契约测试捕获。

3.5 选型权衡

决策点方案A方案B建议场景
策略层是否独立为微服务嵌入 SDK独立 sidecar简单场景用 SDK;多语言或策略热更新用 sidecar
接口层是否提供异步回调仅同步CompletableFuture高吞吐场景推荐异步
实现层适配器数量仅 RedisRedis + Local + 其他混合缓存场景需要 Composite

3.6 风险点与应对

  • 循环依赖:策略层不应反向依赖实现层的具体类,必须通过接口或 SPI 解耦。解决方案是引入 CacheProviderRegistry 实现服务发现。
  • 过度抽象:三层结构在小型项目可能增加复杂性。应对:允许实现层直接提供简单 API 绕过策略层(需配置开关)。
  • 序列化不一致:不同实现层可能要求不同序列化方式。策略层应提供统一的序列化器选择入口。

3.7 落地步骤

  1. 定义接口层接口契约(不少于 5 个核心方法),并编写测试用例。
  2. 实现策略层的 CachePolicyManager 骨架,初始化时注入默认策略。
  3. 选择一个实现层适配器(如 RedisAdapter)进行联调。
  4. 添加配置注入路径(如 yaml 文件读取)。
  5. 编写跨层集成测试,验证请求流转完整性。

3.8 验收标准

本章架构蓝图通过验收需满足:

  • 层间隔离:接口层代码不引入任何实现层 import(通过 SPI 或工厂类)。
  • 策略可替换:修改 cache-policy.yml 即可切换 TTL 策略,无需改动代码。
  • 数据流可观测:在策略层增加一条日志,即能输出完整的调用链路。
  • 依赖图一致性:自动化工具(如 Dependency Graph)检查无循环依赖。
实践提示: 验收阶段建议使用
./gradlew dependencies --configuration runtimeClasspath
确认各模块之间无反向依赖。若发现策略层引用了 RedisAdapter,则视为架构违规。