1.1 缓存基础概念
1.1.1 缓存的定义
缓存(Cache)是一种将数据临时存储在高速存储介质中的技术,其核心思想是“空间换时间”——用额外的存储空间换取更快的访问速度。在软件架构中,缓存位于应用程序与慢速数据源(如数据库、磁盘文件、远程服务)之间,充当一个中间层。
缓存本质: 将最近或最频繁访问的数据复制到更快的存储层,使后续请求可以直接从高速层获取,避免重复执行昂贵的计算或 I/O 操作。
缓存系统通常具备以下三个基本特征:
- 临时性: 缓存中的数据通常有生命周期(TTL),过期后会被自动清除或刷新。
- 局部性: 利用时间局部性(刚访问的数据很可能再次被访问)和空间局部性(相邻数据很可能被一起访问)来提升命中率。
- 透明性: 对上层应用而言,缓存的存在应当是透明的——应用代码无需感知缓存的具体实现细节。
1.1.2 缓存的核心作用
缓存系统在软件架构中承担两个核心使命:加速 和 保护。
| 作用维度 | 具体描述 | 典型场景 |
|---|---|---|
| 加速访问 | 将热点数据存储在内存中,将读取延迟从毫秒级(数据库)降低到微秒级(缓存)。 | 商品详情页、用户会话信息、配置参数 |
| 保护后端 | 拦截大量重复请求,减少数据库连接数、磁盘 I/O 和计算压力,防止后端系统过载。 | 秒杀活动、热点新闻、API 限流降级 |
| 削峰填谷 | 在流量突发时吸收瞬时请求峰值,平滑后端负载曲线。 | 电商大促、微博热搜、抢票系统 |
经验法则: 缓存命中率低于 80% 时,需要重新审视缓存策略——要么数据热度评估不准,要么缓存容量配置不足。
1.1.3 缓存 vs 数据库:核心差异
缓存与数据库在设计目标、数据模型、访问模式上存在本质区别。下表从多个维度进行对比:
| 对比维度 | 缓存(以 Redis 为例) | 关系型数据库(以 MySQL 为例) |
|---|---|---|
| 存储介质 | 内存(DRAM)为主,可选持久化 | 磁盘(SSD/HDD)为主 |
| 读写速度 | 微秒级(0.1~1ms) | 毫秒级(1~100ms) |
| 数据模型 | Key-Value、哈希、列表、集合等简单结构 | 表、行、列、关系、索引、约束 |
| 查询能力 | 基于 Key 的简单查询,有限的范围/排序 | SQL 复杂查询、多表 JOIN、聚合、子查询 |
| 事务支持 | 有限事务(MULTI/EXEC),不支持回滚 | ACID 强事务,支持回滚和隔离级别 |
| 持久化 | 可选(RDB/AOF),非强保证 | 强持久化,WAL 日志,崩溃恢复 |
| 数据容量 | 受限于内存大小(GB~TB 级) | 可扩展至 PB 级(分库分表) |
| 一致性 | 最终一致性为主,弱一致性 | 强一致性(ACID) |
| 主要用途 | 加速、缓存、会话、计数器、消息队列 | 持久化存储、复杂查询、数据完整性 |
常见误区: 不要试图用缓存替代数据库。缓存不是数据库的“替代品”,而是“加速器”。缓存数据丢失后,必须能从数据库恢复;数据库才是数据的最终权威来源(Source of Truth)。
1.1.4 缓存与数据库的协作关系
在典型 Web 应用中,缓存与数据库形成分层协作架构。下图展示了请求从客户端到后端存储的完整路径:
1.1.5 缓存使用的基本原则
在实际项目中,缓存的使用需要遵循以下原则,否则可能引入数据不一致、内存浪费等问题:
- 只缓存热点数据: 缓存容量有限,只缓存访问频率高、计算代价大的数据。全量缓存通常不可取。
- 设置合理的 TTL: 所有缓存数据必须有过期时间,避免“僵尸数据”长期占用内存。
- 容忍最终一致性: 缓存数据允许短暂过期,业务上必须能接受缓存与数据库之间的短暂不一致。
- 缓存穿透防护: 对不存在的数据也要缓存空值(Null Cache)或使用布隆过滤器,防止恶意请求穿透缓存直达数据库。
- 缓存雪崩防护: 避免大量缓存同时过期,采用随机 TTL、多级缓存、限流降级等策略。
领域驱动设计视角: 在 DDD 中,缓存通常属于基础设施层(Infrastructure Layer),为领域层和应用层提供高性能数据访问能力。缓存策略不应侵入领域逻辑,而应通过仓储接口(Repository Interface)的装饰器模式或 AOP 切面实现,保持领域模型的纯净。
1.1.6 缓存命中率与性能指标
衡量缓存系统健康度的核心指标包括:
| 指标名称 | 计算公式 | 健康阈值 | 说明 |
|---|---|---|---|
| 缓存命中率 | 命中次数 / (命中次数 + 未命中次数) | > 90% | 命中率越高,缓存效果越好 |
| 平均访问延迟 | 总响应时间 / 请求总数 | < 5ms | 包含网络开销和序列化/反序列化 |
| 缓存穿透率 | 未命中且数据不存在的次数 / 总请求数 | < 1% | 过高说明存在恶意攻击或设计缺陷 |
| 内存利用率 | 已用内存 / 最大内存 | 60%~80% | 预留空间给突发流量和内存碎片 |
实战建议: 在 Redis 中通过
INFO stats 命令可以查看 keyspace_hits 和 keyspace_misses 指标,实时计算命中率。建议将命中率监控纳入告警体系,低于 85% 时触发预警。