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,考虑“永不过期 + 后台异步刷新”策略。
缓存与数据库对比架构图 应用程序 缓存层(Redis) 内存 · 微秒级 · 键值结构 数据库层(MySQL) 磁盘 · 毫秒级 · 关系模型 缓存命中:直接返回,延迟 < 1ms 缓存未命中:穿透到数据库,延迟 10~50ms 缓存容量:GB 级,成本高 数据库容量:TB 级,成本低 缓存命中与失效处理流程 客户端请求 缓存命中? 是 返回缓存数据 否 查询数据库 回填缓存 返回数据 缓存失效场景 TTL 过期 → 惰性删除 / 定期扫描 | 内存淘汰 → LRU/LFU/TTL | 数据更新 → 先更新 DB,再删除缓存 雪崩:大量 key 同时过期 | 击穿:热点 key 过期 | 穿透:查询不存在的数据