1. 缓存基础概念
1.1 什么是缓存
缓存(Cache)是一种将数据存储在临时高速存储层中的技术,目的是让后续对相同数据的访问更快。缓存通常位于速度较慢的持久化存储(如数据库、磁盘)与应用程序之间,充当“中间加速层”。
核心定义:缓存是空间换时间的经典实践——用额外的存储空间(内存)换取更短的数据访问延迟。
缓存可以存在于计算机系统的多个层级:
- CPU 缓存(L1/L2/L3)—— 减少内存访问延迟
- 操作系统缓存(Page Cache、Buffer Cache)—— 加速磁盘 I/O
- 应用层缓存(Redis、Memcached)—— 加速数据库查询与计算
- CDN 缓存—— 加速静态资源分发
本课程聚焦应用层缓存,以 Redis 为核心,探讨缓存读写分离架构下的领域边界与实战策略。
1.2 缓存的作用
缓存的核心价值体现在以下四个维度:
| 维度 | 作用描述 | 典型效果 |
|---|---|---|
| 降低延迟 | 内存访问延迟通常在微秒级,远低于磁盘 I/O(毫秒级) | 响应时间从 50ms → 1ms |
| 提升吞吐 | 缓存可承载每秒数万至数十万次请求,远超数据库 | QPS 从 1k → 100k+ |
| 保护后端 | 缓存吸收热点请求,减少数据库连接数与负载 | 数据库 CPU 从 90% → 20% |
| 削峰填谷 | 应对突发流量,缓存作为缓冲层平滑请求波峰 | 秒杀场景下数据库不被打垮 |
实践提示:缓存不是银弹。缓存引入会带来数据一致性、过期策略、内存管理等新问题。缓存的价值在于命中率足够高且数据一致性可接受的场景。
1.3 缓存与数据库的对比
理解缓存与数据库的本质差异,是设计缓存策略的前提。下表从多个关键维度进行对比:
| 对比维度 | 缓存(Redis 为例) | 数据库(MySQL 为例) |
|---|---|---|
| 存储介质 | 内存(DRAM) | 磁盘(SSD/HDD) |
| 读写延迟 | 微秒级(0.1ms ~ 1ms) | 毫秒级(1ms ~ 50ms) |
| 数据容量 | 受限于内存大小(GB ~ 百GB) | TB ~ PB 级 |
| 数据持久性 | 默认非持久化(可配置 RDB/AOF) | 强持久化(ACID 事务) |
| 查询能力 | 键值操作 + 简单数据结构 | 复杂 SQL、JOIN、事务 |
| 一致性模型 | 最终一致性为主 | 强一致性(可配置) |
| 成本 | 高(内存价格远高于磁盘) | 低(磁盘存储成本低) |
常见误区:不要试图用缓存替代数据库。缓存是加速层,数据库是真相源(Source of Truth)。缓存数据丢失后,必须能从数据库恢复。
1.4 缓存命中率与失效
1.4.1 缓存命中率
缓存命中率(Cache Hit Ratio)是衡量缓存效率的核心指标:
缓存命中率 = 缓存命中的请求数 / 总请求数 × 100%
命中率的分级参考:
- 优秀:命中率 > 95% —— 缓存设计合理,数据访问局部性强
- 良好:命中率 80% ~ 95% —— 大部分请求被缓存覆盖
- 一般:命中率 50% ~ 80% —— 需要优化缓存策略或扩大缓存范围
- 较差:命中率 < 50% —— 缓存可能形同虚设,需重新评估
关键公式:缓存有效吞吐 = 总吞吐 × 命中率。命中率每提升 10%,数据库压力可降低 30%~50%。
1.4.2 缓存失效
缓存失效是指缓存中的数据不再有效,需要从数据库重新加载。常见的失效场景包括:
| 失效类型 | 触发条件 | 典型处理方式 |
|---|---|---|
| TTL 过期 | 缓存设置了过期时间,时间到达后自动失效 | 惰性删除 + 定期扫描 |
| 主动淘汰 | 内存不足时,根据淘汰策略(LRU/LFU/TTL)移除数据 | Redis maxmemory-policy 配置 |
| 数据更新 | 数据库数据被修改,缓存需要同步更新或删除 | Cache-Aside 模式:先更新 DB,再删除缓存 |
| 缓存雪崩 | 大量缓存同时过期,导致请求全部穿透到数据库 | 过期时间加随机偏移、多级缓存 |
| 缓存击穿 | 热点 key 过期,高并发请求同时穿透 | 互斥锁、永不过期 + 异步更新 |
1.4.3 缓存失效的连锁问题
缓存失效不仅仅是数据过期,还会引发一系列架构问题:
- 缓存穿透:查询一个不存在的数据,缓存和数据库都查不到,每次请求都打到数据库
- 缓存击穿:热点 key 失效,大量并发请求同时访问数据库
- 缓存雪崩:大量 key 同时失效,数据库瞬间被压垮
最佳实践:设置 TTL 时加入随机偏移(如基础 TTL + random(0, 300) 秒),避免大量 key 同时过期。对于热点 key,考虑“永不过期 + 后台异步刷新”策略。