2. 缓存基础:定义、作用与常见策略
在分布式系统与容器化架构中,缓存是提升性能、降低延迟、保护后端数据库的关键手段。本章将系统梳理缓存的核心定义、作用以及四种主流缓存策略,为后续在 Docker 环境中实现缓存一致性治理奠定理论基础。
2.1 缓存的定义
缓存(Cache)是一种将数据临时存储在高速存储介质中的技术,其核心思想是“空间换时间”。当应用程序需要访问数据时,首先从缓存中查找;如果命中,则直接返回,避免对较慢的后端存储(如数据库、磁盘)发起重复查询。
2.2 缓存的作用
在容器化微服务架构中,缓存承担着以下关键角色:
| 作用维度 | 具体说明 | 典型场景 |
|---|---|---|
| 降低延迟 | 内存访问延迟通常在微秒级,远低于磁盘 I/O(毫秒级)或网络 RPC | 用户会话、商品详情页 |
| 提升吞吐量 | 缓存可承载数万 QPS,减轻后端数据库连接池压力 | 秒杀活动、热点新闻 |
| 保护后端 | 缓存层作为缓冲,防止突发流量击穿数据库 | 限流、降级场景 |
| 减少成本 | 减少数据库实例扩容需求,降低硬件与运维成本 | 读多写少业务 |
2.3 常见缓存策略
不同的业务场景需要匹配不同的缓存读写策略。以下是四种最经典的策略,也是容器化缓存治理项目中最常涉及的方案。
2.3.1 Cache-Aside(旁路缓存)
Cache-Aside 是应用最广泛的策略,应用程序直接同时管理缓存和数据库。读操作时,先查缓存,未命中则查数据库并回写缓存;写操作时,先更新数据库,再删除缓存(或更新缓存)。
// 读操作伪代码
function read(key):
data = cache.get(key)
if data is null:
data = db.query(key)
cache.set(key, data, ttl)
return data
// 写操作伪代码
function write(key, value):
db.update(key, value)
cache.del(key) // 删除缓存,而非更新
2.3.2 Read-Through(穿透读)
Read-Through 将缓存层抽象为一个统一的读取入口。应用程序只与缓存交互,缓存组件(如 Redis、Memcached)在未命中时自动从数据库加载数据并回填。这种方式对应用层更透明,但缓存组件需要具备数据加载能力。
// 应用层代码更简洁
function read(key):
return cache.get(key) // 缓存内部自动处理回源逻辑
2.3.3 Write-Through(穿透写)
Write-Through 与 Read-Through 配合使用。写操作时,应用程序将数据写入缓存,缓存组件同步将数据写入数据库。优点是数据一致性高,缺点是每次写操作都会产生两次写入(缓存 + 数据库),延迟较高。
// 写操作伪代码
function write(key, value):
cache.set(key, value) // 缓存同步写入数据库
// 缓存内部自动执行: db.update(key, value)
2.3.4 Write-Behind(异步写回)
Write-Behind 策略中,应用程序只写入缓存,缓存组件异步批量地将数据写入数据库。这种方式能极大提升写吞吐量,适合写密集型场景(如日志收集、埋点数据)。但存在数据丢失风险(缓存宕机时未持久化的数据会丢失)。
2.4 四种策略对比
| 策略 | 一致性强度 | 写延迟 | 读延迟 | 应用复杂度 | 适用场景 |
|---|---|---|---|---|---|
| Cache-Aside | 最终一致(需处理并发) | 低(仅删缓存) | 低(命中时) | 中 | 通用业务,读多写少 |
| Read-Through | 最终一致 | — | 低(缓存自动回源) | 低(应用层) | 需要缓存抽象层 |
| Write-Through | 强一致 | 高(双写) | 低 | 低(应用层) | 对一致性要求极高 |
| Write-Behind | 最终一致(有丢失风险) | 极低(异步) | 低 | 高(需补偿) | 写密集型、日志类 |
2.5 缓存策略架构图
下图展示了四种缓存策略在应用、缓存、数据库三层之间的数据流向关系,帮助理解每种策略的读写路径差异。
2.6 策略选择建议
在容器化缓存一致性治理项目中,策略选择直接影响架构复杂度与一致性保障成本:
- 通用业务(如用户信息、商品详情): 优先选择 Cache-Aside,配合 TTL 和缓存删除机制,实现最终一致性。
- 需要缓存抽象层(如使用 Redis 作为唯一数据入口): 选择 Read-Through / Write-Through 组合,降低应用层耦合。
- 写密集型场景(如日志、埋点、IoT 数据): 考虑 Write-Behind,但必须引入消息队列或持久化机制防止数据丢失。
- 强一致性要求(如金融交易、库存扣减): 避免仅依赖缓存,应使用分布式锁或数据库事务保证数据准确。