2. 缓存基础:缓存工作原理、常见缓存模式与失效策略
在 CI/CD 管道中引入缓存,核心目标是加速构建、测试与部署流程,减少重复计算与网络 I/O。理解缓存的工作原理与常见模式,是治理缓存一致性、设计自动化索引选择策略的前提。本节从缓存核心机制出发,系统梳理三种主流缓存模式与四种失效策略。
2.1 缓存工作原理
缓存本质上是高速数据暂存层,位于原始数据源(数据库、文件系统、远程 API)与消费者之间。其工作流程遵循“读时填充、写时更新/失效”的基本逻辑:
- 读请求到达:消费者首先查询缓存。
- 缓存命中:若缓存中存在目标数据,直接返回,延迟极低(通常 < 1ms)。
- 缓存未命中:若缓存中不存在,则回源查询数据库或远程服务。
- 回填缓存:将查询结果写入缓存,并设置 TTL(过期时间),供后续请求使用。
- 返回数据:将数据返回给消费者。
关键指标:缓存命中率(Cache Hit Ratio)是衡量缓存效率的核心指标。CI/CD 场景下,依赖包缓存、Docker 层缓存的目标命中率应 ≥ 90%,否则缓存带来的收益会被回源开销抵消。
2.2 常见缓存模式
不同的缓存模式决定了数据在缓存与数据源之间的同步策略。在 CI/CD 管道中,选择正确的模式直接影响构建产物的一致性与可用性。以下为三种最常用的模式:
| 模式 | 读策略 | 写策略 | 一致性保证 | CI/CD 典型场景 |
|---|---|---|---|---|
| Cache-Aside | 应用先读缓存,未命中则回源并回填 | 应用直接写数据库,然后显式失效缓存 | 最终一致性(需处理并发写失效) | 依赖包缓存、Docker 镜像层缓存 |
| Read-Through | 缓存层自动回源并回填,应用只与缓存交互 | 应用直接写数据库,缓存由失效机制同步 | 最终一致性(缓存层封装回源逻辑) | 构建产物元数据缓存、测试 fixture 缓存 |
| Write-Through | 同 Read-Through | 应用写缓存,缓存同步写数据库(同步或异步) | 强一致性(写缓存即写数据库) | 管道状态记录、构建锁、分布式计数器 |
选型建议:CI/CD 管道中,Cache-Aside 是最灵活的模式,适合读多写少的依赖缓存;Write-Through 适合需要强一致性的管道状态数据;Read-Through 适合希望简化应用逻辑、由缓存层统一管理回源的场景。
2.3 缓存失效策略
缓存失效策略决定了数据何时从缓存中移除,是治理缓存一致性的关键。错误的失效策略会导致“脏数据”或“缓存雪崩”。以下为四种核心策略:
- TTL(Time-To-Live)过期:为每个缓存条目设置固定生存时间(如 300 秒)。到期后自动失效。适用于对实时性要求不高的构建产物缓存。
- LRU(Least Recently Used)淘汰:当缓存空间满时,淘汰最久未使用的条目。适用于内存有限的本地缓存场景。
- 主动失效(Explicit Invalidation):当数据源发生变更时,应用主动删除或更新缓存中的对应条目。适用于需要强一致性的管道状态。
- 版本化失效(Version-based Invalidation):为缓存键附加版本号(如
pkg:v1.2.3),版本变更时自动切换缓存。适用于依赖包、Docker 镜像等不可变产物。
2.4 缓存模式与失效策略的组合选型
在实际 CI/CD 管道中,缓存模式与失效策略需要组合使用。以下为推荐组合矩阵:
| 缓存模式 | 推荐失效策略 | 理由 |
|---|---|---|
| Cache-Aside | TTL + 主动失效 | TTL 兜底防止永久脏数据,主动失效在构建完成后立即刷新 |
| Read-Through | TTL + LRU | 缓存层自动管理回源,TTL 控制数据新鲜度,LRU 控制内存 |
| Write-Through | 主动失效 / 版本化 | 写操作同步到数据库,缓存必须与数据库保持强一致 |
避坑提示:不要在所有场景都使用 TTL。对于管道状态锁、构建队列计数器等需要强一致性的数据,必须使用主动失效或版本化失效,否则会导致管道状态不一致、构建冲突等严重问题。
2.5 缓存一致性治理的起点
缓存一致性治理的核心在于:明确数据的新鲜度要求。在 CI/CD 管道中,不同数据对一致性的容忍度不同:
- 强一致性要求:管道状态、构建锁、部署记录 → 使用 Write-Through + 主动失效。
- 最终一致性要求:依赖包缓存、Docker 层缓存 → 使用 Cache-Aside + TTL。
- 弱一致性要求:构建日志、测试报告快照 → 使用 Read-Through + TTL + LRU。