# 缓存系统设计:从淘宝商品详情页看高性能架构 > 💡 **学习指南**:为什么用户点击淘宝商品详情页只需要 50 毫秒,而直接查数据库要 500 毫秒?这背后是一个精心设计的缓存架构在发挥作用。本章节将带你深入理解缓存的本质、模式与实战技巧。 --- ## 0. 引言:为什么系统越来越慢? ### 0.1 一个真实的性能危机 2020 年双十一,某电商平台的数据库 CPU 使用率突然飙到 95%,订单查询响应时间从 100ms 暴涨到 8 秒。问题根源很快查明:一个新上线的促销页面,每次加载都要查询 50+ 次数据库,且没有缓存。 **核心问题暴露**——当流量激增时,数据库成为整个系统的瓶颈。 | 操作类型 | 响应时间 | 单节点 QPS | 瓶颈分析 | | :------- | :------- | :--------- | :------- | | L1 Cache 读取 | ~0.5 ns | 数十亿级 | CPU 内置,无瓶颈 | | 内存读取 | ~100 ns | 百万级 | 内存带宽 | | Redis 查询 | ~1 ms | 10万级 | 网络延迟 | | MySQL 查询 | ~10 ms | 数千级 | 磁盘 IO | | 跨机房查询 | ~100 ms | 百级 | 网络距离 | **性能差距触目惊心**:内存操作比 MySQL 查询快 100,000 倍。 ### 0.2 缓存的本质定义 缓存不是简单地把数据存到内存,而是一种**基于局部性原理的数据访问优化技术**。 **严格定义**:缓存是位于计算单元与慢速存储之间的高速数据存储层,通过存储最近或频繁访问数据的副本,减少访问延迟、提升系统吞吐量。 **与原始存储的核心区别**: - 原始存储(数据库):容量大、持久化、查询慢 - 缓存:容量有限、易失性、查询极快 - 缓存内容永远是原始数据的**副本**,而非主数据 ### 0.3 淘宝商品详情页的缓存实战 让我们拆解一个真实的电商商品详情页,看看缓存是如何层层发挥作用的。 **场景**:用户打开商品 ID 为 12345 的详情页。 **访问链路**(从上到下,层层穿透): | 层级 | 存储位置 | 查询耗时 | 数据示例 | 命中率 | | :--- | :------- | :------- | :------- | :----- | | L1 | 浏览器本地缓存 | ~0ms | 静态图片、CSS、JS | 95%+ | | L2 | CDN 边缘节点 | ~20ms | 商品主图、详情图 | 90%+ | | L3 | Nginx 本地缓存 | ~1ms | 商品基础信息 JSON | 80%+ | | L4 | 应用进程本地缓存 (Caffeine) | ~0.1ms | 热销商品详情 | 90%+ | | L5 | Redis 集群 | ~2ms | 所有商品信息、库存 | 99%+ | | L6 | MySQL 主从集群 | ~10ms | 全量商品数据 | 100% | **最终效果**: - 95% 的请求在前 4 层就被拦截,根本不会到达数据库 - 整体响应时间:P99 < 100ms - 数据库 QPS 从理论上的 100万+ 下降到实际 5000 以下 --- ## 1. 缓存的底层原理:局部性 缓存之所以有效,根植于计算机科学中一个被反复验证的观察:**局部性原理**。 ### 1.1 时间局部性 (Temporal Locality) **定义**:如果一个数据项被访问,那么在不久的将来它很可能再次被访问。 **技术解释**:程序在执行过程中,往往会对某些变量或数据对象进行反复读取或修改。这是因为: - 循环结构会重复访问相同的计数器变量 - 函数调用会重复访问相同的参数和局部变量 - 热点数据(如用户会话、配置项)会被频繁查询 **实例**:用户登录后,系统需要反复查询该用户的权限信息。第一次查询后将结果缓存,后续几十次请求都可以直接从缓存获取,直到用户登出或权限变更。 ### 1.2 空间局部性 (Spatial Locality) **定义**:如果一个数据项被访问,那么与它地址相邻的数据项也很可能被访问。 **技术解释**:计算机存储和访问数据的方式天然具有连续性: - 内存以缓存行(通常 64 字节)为单位加载数据 - 数组、列表等数据结构在内存中连续存储 - 磁盘读取以块(通常 4KB)为单位 - 业务数据往往按时间、分类等维度聚簇存储 **实例**:加载商品列表时,如果缓存了第 1-10 条商品数据,当用户翻页到第 11-20 条时,这些相邻的数据很可能已经被批量加载到缓存中,实现快速响应。 ### 1.3 缓存的生命周期 一个缓存条目从创建到销毁,经历完整的生命周期: ``` 写入 (Write) → 命中/未命中 (Hit/Miss) → 过期 (Expiration) → 淘汰 (Eviction) ``` **写入策略**: - **主动写入**:系统启动时预加载热点数据(缓存预热) - **懒加载**:首次访问时从数据库加载并写入缓存 - **异步更新**:后台线程定期刷新即将过期的数据 **过期策略**: - **TTL (Time To Live)**:设置固定生存时间,到期自动失效 - **滑动过期**:每次访问后重置过期时间 - **绝对过期**:指定具体过期时间点 **淘汰策略**(缓存满时): - **LRU (Least Recently Used)**:淘汰最近最少使用(最常用) - **LFU (Least Frequently Used)**:淘汰访问频率最低 - **FIFO (First In First Out)**:先进先出 - **Random**:随机淘汰 --- ## 2. 缓存架构选型 ### 2.1 本地缓存 (Local Cache) **定义**:与应用进程共享内存空间的缓存,无需网络访问。 **技术特点**: - **访问延迟**:~100 纳秒(纯内存访问,无网络开销) - **容量限制**:受限于单机内存(通常几百 MB 到几 GB) - **一致性挑战**:多实例部署时,各节点缓存独立,数据可能不一致 - **进程绑定**:应用重启,缓存丢失 **主流实现**: | 语言 | 库/框架 | 核心特性 | | :--- | :------ | :------- | | Java | Caffeine | 高性能,W-TinyLFU 淘汰算法,近乎完美的命中率 | | Java | Guava Cache | 功能全面,但性能略逊于 Caffeine | | Go | Ristretto | 高性能,高命中率,支持过期 | | Go | BigCache | 专为大量 entry 设计,零 GC 压力 | | Python | cachetools | 多种缓存策略,TTL 支持 | ### 2.2 分布式缓存 (Distributed Cache) **定义**:作为独立服务部署的缓存系统,通过网络协议访问,多实例共享。 **技术特点**: - **访问延迟**:~1-5 毫秒(网络开销) - **容量扩展**:支持集群部署,容量可达数百 GB 甚至 TB - **一致性保证**:所有应用实例访问同一份数据,天然一致 - **高可用**:支持主从复制、哨兵、集群模式 **主流实现对比**: | 特性 | Redis | Memcached | | :--- | :---- | :---------- | | 数据结构 | String, Hash, List, Set, ZSet, Stream 等 | 仅 String | | 持久化 | RDB, AOF 支持 | 不支持 | | 集群 | Redis Cluster, Codis | 客户端分片 | | 单线程/多线程 | 单线程(命令执行)| 多线程 | | 内存管理 | 支持内存淘汰策略 | LRU 淘汰 | | 适用场景 | 复杂数据结构、持久化需求 | 纯缓存、简单 KV | ### 2.3 多级缓存架构 在真实的生产环境中,单一缓存层往往无法满足性能和成本的双重需求。多级缓存架构通过在不同层级部署缓存,形成层层防护,最大化性能收益。 **典型多级缓存架构**: ``` ┌─────────────────────────────────────────────────────────────────┐ │ 用户请求 │ └─────────────────────────┬───────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ │ L1: 浏览器缓存 (Browser Cache) │ │ - 存储:静态资源 (CSS/JS/图片) │ │ - 控制:Cache-Control, ETag, Last-Modified │ │ - 延迟:~0ms (本地磁盘/内存) │ └─────────────────────────┬───────────────────────────────────────┘ ↓ (未命中) ┌─────────────────────────────────────────────────────────────────┐ │ L2: CDN 缓存 (Content Delivery Network) │ │ - 存储:静态资源、部分 API 响应 │ │ - 节点:全球分布,就近访问 │ │ - 延迟:~20-50ms │ └─────────────────────────┬───────────────────────────────────────┘ ↓ (未命中) ┌─────────────────────────────────────────────────────────────────┐ │ L3: 反向代理缓存 (Nginx/Varnish) │ │ - 存储:完整 HTTP 响应、聚合数据 │ │ - 延迟:~1-5ms │ └─────────────────────────┬───────────────────────────────────────┘ ↓ (未命中) ┌─────────────────────────────────────────────────────────────────┐ │ L4: 应用本地缓存 (Caffeine/Guava) │ │ - 存储:热点对象、配置、用户会话 │ │ - 延迟:~0.1ms │ └─────────────────────────┬───────────────────────────────────────┘ ↓ (未命中) ┌─────────────────────────────────────────────────────────────────┐ │ L5: 分布式缓存 (Redis Cluster) │ │ - 存储:业务数据、会话、计算结果 │ │ - 延迟:~1-5ms │ └─────────────────────────┬───────────────────────────────────────┘ ↓ (未命中) ┌─────────────────────────────────────────────────────────────────┐ │ L6: 数据库 (MySQL/PostgreSQL) │ │ - 存储:全量数据 │ │ - 延迟:~10-50ms │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## 3. 缓存设计模式 当引入缓存层后,应用程序需要确定如何与缓存和数据库交互。业界形成了四种经典的设计模式,每种模式在一致性、性能和复杂度之间做出不同的权衡。 ### 3.1 Cache-Aside (旁路缓存) — 最常用 **模式定义**:应用程序负责直接管理缓存,显式地从缓存读取、写入数据。缓存对数据库完全透明,不知道数据库的存在。 **读取流程**: ``` 应用程序 ─┬─→ 查询缓存 ──→ 命中?─┬─是→ 返回数据 │ │ │ └─否→ 查询数据库 │ ↓ │ 写入缓存 │ ↓ └──────────────────────── 返回数据 ``` **更新流程**(关键!): ``` 应用程序 ──→ 更新数据库 ──→ 删除缓存(不是更新缓存!) ``` ### 3.2 Read-Through (读穿透) **模式定义**:应用程序只与缓存交互,缓存层负责在缺失时自动从数据库加载数据。对应用程序完全透明。 **工作原理**: ``` 应用程序 ──→ 查询缓存 ──→ 未命中 ──→ 缓存服务自动加载数据库数据 ↓ 返回给应用 ``` **优缺点对比**: | 维度 | Read-Through | Cache-Aside | | :--- | :----------- | :------------ | | 代码复杂度 | 低(业务代码无缓存逻辑) | 中(显式管理缓存) | | 灵活性 | 低(受限于缓存库实现) | 高(完全控制) | | 首次加载延迟 | 较高(穿透到库) | 可控(可预热) | | 适用场景 | 标准化缓存需求 | 复杂业务逻辑 | ### 3.3 Write-Through (写穿透) **模式定义**:应用程序写入缓存,缓存服务同步将数据写入数据库,确保缓存和数据库强一致。 **工作原理**: ``` 应用程序 ──→ 写入缓存 ──→ 缓存服务同步写入数据库 ──→ 返回成功 ``` **特点**: - **强一致性**:缓存和数据库始终一致 - **写入延迟高**:需等待数据库写入完成 - **吞吐量受限**:受限于数据库写入能力 **适用场景**: - 对数据一致性要求极高的场景(金融交易、库存扣减) - 写操作相对较少的场景 ### 3.4 Write-Behind (异步写回) **模式定义**:应用程序只写入缓存,缓存服务异步批量将数据写入数据库。 **工作原理**: ``` 应用程序 ──→ 写入缓存(立即返回) ↓ 后台异步批量写入数据库 ``` **核心优势**: - **写入极快**:~1ms 延迟,10万+ QPS - **批量写入**:减少数据库 IO,提升吞吐量 - **削峰填谷**:将突发流量平滑化 **核心风险**: - **数据丢失风险**:缓存宕机,未写入数据库的数据丢失 - **数据不一致窗口**:异步写入期间,缓存与数据库不一致 --- ## 4. 缓存的三大经典问题 在实际生产环境中,缓存可能引入三类严重问题,需要系统性解决方案。 ### 4.1 缓存穿透 (Cache Penetration) **问题定义**:查询一个**不存在的数据**,缓存中没有(因为没有),数据库中也没有,导致每次请求都直接打到数据库。 **攻击场景**: - 恶意攻击者构造大量不存在的 ID 进行查询(如 id=-1, id=999999999) - 爬虫遍历不存在的资源路径 - 业务逻辑错误导致查询无效数据 **解决方案 1:布隆过滤器 (Bloom Filter)** **原理**:在缓存之前加一层概率型数据结构,快速判断"这个 key **肯定不存在**或**可能存在**"。 **特性**: - 100% 判断不存在(绝对不会误判为存在) - 可能误判存在(实际不存在,但过滤器说可能存在,概率可调) ### 4.2 缓存击穿 (Cache Breakdown) **问题定义**:某个**热点数据**在缓存中过期(TTL 到期),此时大量并发请求同时到达,都去查询数据库,导致数据库压力骤增。 **典型场景**: - 微博热搜榜过期瞬间 - 明星八卦新闻缓存失效 - 秒杀活动开始时的库存数据 - 热门商品的缓存同时过期 **解决方案 1:互斥锁 (Mutex Lock)** **原理**:当缓存失效时,只允许一个线程去查询数据库并重建缓存,其他线程等待或重试。 **解决方案 2:逻辑过期 (Logical Expiration)** **原理**:不设置物理过期时间(TTL),而是在缓存 value 中嵌入逻辑过期时间字段。发现逻辑过期时,异步重建缓存,同时返回旧数据(永不过期)。 ### 4.3 缓存雪崩 (Cache Avalanche) **问题定义**:大量缓存数据在**同一时间点集中过期**(或 Redis 宕机),导致所有请求同时穿透到数据库,瞬间压垮数据库。 **典型触发场景**: - 系统重启后,所有缓存从 0 开始重建,同时设置相同 TTL - 定时任务批量刷新缓存,设置相同的过期时间 - 缓存服务(Redis)宕机或网络分区 - 大量热点数据同时达到过期时间 **解决方案 1:随机 TTL (Time To Live)** **原理**:在基础过期时间上增加随机偏移量,打散过期时间点。 **解决方案 2:缓存预热 (Cache Preheating)** **原理**:系统启动或定时任务主动将热点数据加载到缓存,避免冷启动时集中回源。 **解决方案 3:熔断降级 (Circuit Breaker)** **原理**:当数据库压力过大时,暂时拒绝部分请求或返回降级数据,保护数据库不被压垮。 --- ## 5. 缓存一致性策略 缓存的本质是数据的副本,副本与主数据(数据库)之间必然存在不一致的时间窗口。如何控制这个时间窗口,是缓存设计的核心挑战。 ### 5.1 为什么不一致? **并发写入场景**: | 时间 | 线程 A(更新 age=25) | 线程 B(查询) | 数据库 | 缓存 | | :--- | :-------------------- | :------------- | :----- | :--- | | T1 | 更新 DB age=25 | - | 25 | 20(旧值) | | T2 | - | 查询缓存(命中旧值) | 25 | 20 ❌ | | T3 | 删除缓存 | - | 25 | - | | T4 | - | - | 25 | 从 DB 加载 25 ✅ | **问题**:在 T2 时刻,线程 B 读取到了缓存中的旧值 20,而此时数据库已经是 25。 ### 5.2 最佳实践:先更新数据库,再删除缓存 **原理**:利用数据库的行锁机制,保证"更新"操作的排他性,最大限度减少不一致窗口。 **流程**: ``` 写请求 ──→ 开启数据库事务 ──→ 更新数据库记录 ──→ 提交事务 ──→ 删除缓存 ``` **为什么这个顺序最优?** 1. **数据库锁保护**:更新操作会获取行锁,其他读写操作必须等待,天然排他 2. **删除缓存是异步操作**:不需要等待缓存删除成功,数据库提交后即可返回 3. **极端情况仍可接受**:即使缓存删除失败,只是下次读取会回源,不会导致脏数据长期存在 ### 5.3 延迟双删 (Delayed Double Deletion) **场景**:先删缓存、再写 DB 的方案在极端并发下仍有不一致风险。延迟双删通过两次删除,最大限度保证一致性。 **流程**: ``` 1. 删除缓存 2. 更新数据库 3. 等待一段时间(如 500ms) 4. 再次删除缓存 ``` **三种一致性策略对比**: | 策略 | 一致性级别 | 性能影响 | 复杂度 | 适用场景 | | :--- | :--------- | :--------- | :------- | :------- | | 先更新 DB,再删缓存 | 最终一致 | 低 | 低 | 大多数场景,推荐作为默认方案 | | 延迟双删 | 强最终一致 | 中(延迟) | 中 | 对一致性要求较高的场景 | | 先删缓存,再更新 DB | 弱 | 低 | 低 | 不推荐,易出现不一致 | --- ## 6. 实战:构建高性能缓存系统 ### 6.1 场景分析:电商商品详情页 **业务特点**: - 读多写少:100:1 的读写比 - 热点集中:20% 的商品贡献 80% 的流量 - 数据复杂度:商品基础信息 + 价格 + 库存 + 评价聚合 - 一致性要求:价格、库存强一致,其他可最终一致 **性能指标**: - P99 响应时间 < 100ms - 数据库 QPS 峰值 < 5000 - 缓存命中率 > 95% ### 6.2 架构设计 ``` ┌─────────────────────────────────────────────────────────┐ │ 客户端请求 │ └───────────────────────┬─────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────┐ │ CDN 缓存层 │ │ - 商品主图、详情图 │ │ - Cache-Control: max-age=86400 │ └───────────────────────┬─────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────┐ │ Nginx 缓存层 │ │ - 商品基础信息聚合(包含价格、库存) │ │ - proxy_cache_valid 5m │ └───────────────────────┬─────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────┐ │ 应用层 │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ 本地缓存 │ │ 分布式锁 │ │ │ │ (Caffeine) │ │ (Redisson) │ │ │ │ - 热点商品 │ │ - 防击穿 │ │ │ │ - 配置信息 │ │ - 库存扣减 │ │ │ └─────────────────┘ └─────────────────┘ │ └───────────────────────┬─────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────┐ │ Redis 集群 │ │ - 商品详情 Hash │ │ - 库存计数器 String │ │ - 热点商品列表 ZSet │ │ - 分布式锁 │ └───────────────────────┬─────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────┐ │ MySQL 集群 │ │ - 商品主表 │ │ - 库存表(行锁控制并发) │ │ - 订单表 │ └─────────────────────────────────────────────────────────┘ ``` ### 6.3 核心代码实现 **完整的多级缓存实现(Java + Spring Boot)**: ```java @Component public class MultiLevelCache { // 本地缓存:Caffeine private final Cache localCache; @Autowired private StringRedisTemplate redisTemplate; @Autowired private RedissonClient redissonClient; // 缓存层级配置 private static final long LOCAL_TTL_SECONDS = 30; private static final long REDIS_TTL_SECONDS = 300; public MultiLevelCache() { this.localCache = Caffeine.newBuilder() .maximumSize(10_000) .expireAfterWrite(Duration.ofSeconds(LOCAL_TTL_SECONDS)) .recordStats() .build(); } /** * 多级缓存读取(L1: 本地缓存 -> L2: Redis -> L3: 数据库) */ public T get(String key, Class type, Supplier dbLoader) { // L1: 本地缓存 Object localValue = localCache.getIfPresent(key); if (localValue != null) { return type.cast(localValue); } // L2: Redis 缓存(带分布式锁防击穿) String redisKey = "cache:" + key; String redisValue = redisTemplate.opsForValue().get(redisKey); if (StrUtil.isNotBlank(redisValue)) { T value = JSON.parseObject(redisValue, type); // 回填本地缓存 localCache.put(key, value); return value; } // L3: 数据库(带分布式锁) String lockKey = "lock:" + key; RLock lock = redissonClient.getLock(lockKey); try { boolean acquired = lock.tryLock(100, 10, TimeUnit.MILLISECONDS); if (!acquired) { // 获取锁失败,等待后重试 Thread.sleep(50); return get(key, type, dbLoader); } // 双重检查 String doubleCheck = redisTemplate.opsForValue().get(redisKey); if (StrUtil.isNotBlank(doubleCheck)) { return JSON.parseObject(doubleCheck, type); } // 查询数据库 T value = dbLoader.get(); if (value != null) { // 写入 Redis(带随机 TTL) long ttl = REDIS_TTL_SECONDS + RandomUtil.randomInt(-30, 30); redisTemplate.opsForValue().set( redisKey, JSON.toJSONString(value), ttl, TimeUnit.SECONDS ); // 回填本地缓存 localCache.put(key, value); } return value; } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException("获取锁被中断", e); } finally { if (lock.isHeldByCurrentThread()) { lock.unlock(); } } } /** * 删除缓存(更新时调用) */ public void evict(String key) { // 删除本地缓存 localCache.invalidate(key); // 删除 Redis 缓存 redisTemplate.delete("cache:" + key); } } ``` --- ## 7. 总结与学习路径 ### 7.1 核心知识点回顾 | 知识点 | 关键概念 | 实战要点 | | :----- | :------- | :------- | | **局部性原理** | 时间局部性、空间局部性 | 根据访问模式设计缓存 key 和预热策略 | | **多级缓存** | L1-L6 层级 | 浏览器 → CDN → Nginx → 本地 → Redis → DB | | **缓存模式** | Cache-Aside、Read-Through、Write-Through、Write-Behind | Cache-Aside 最常用,Write-Behind 用于高并发写入 | | **缓存穿透** | 查询不存在数据 | 布隆过滤器 + 缓存空对象 | | **缓存击穿** | 热点数据过期 | 互斥锁 + 逻辑过期 | | **缓存雪崩** | 大量数据同时过期 | 随机 TTL + 缓存预热 + 熔断降级 | | **一致性策略** | 先更新 DB 再删缓存、延迟双删 | Cache-Aside + 延迟双删应对极端并发 | ### 7.2 学习路径建议 **阶段 1:理解原理(1-2 天)** - 掌握局部性原理(时间、空间) - 理解缓存生命周期(写入 → 命中 → 过期 → 淘汰) - 了解不同存储介质的性能差异(CPU Cache → 内存 → SSD → HDD) **阶段 2:掌握基础模式(2-3 天)** - 实现 Cache-Aside 模式(读取、更新) - 使用 Redis 做分布式缓存 - 理解为什么"更新时删除缓存而不是更新缓存" **阶段 3:多级缓存实战(3-5 天)** - 实现本地缓存(Caffeine/Guava)+ Redis 的两级架构 - 解决多级缓存的一致性问题 - 实现缓存统计和监控 **阶段 4:解决经典问题(1 周)** - 缓存穿透:实现布隆过滤器 - 缓存击穿:实现互斥锁和逻辑过期 - 缓存雪崩:实现随机 TTL、缓存预热、熔断降级 **阶段 5:一致性保障(1-2 周)** - 深入理解 Cache-Aside 模式的并发问题 - 实现延迟双删 - 了解 Binlog 订阅方案(Canal/Debezium) **阶段 6:生产级实战(持续)** - 设计完整的商品详情页缓存系统 - 搭建 Prometheus + Grafana 监控体系 - 进行压测验证和性能调优 ### 7.3 推荐资源 **书籍**: - 《Redis 设计与实现》(黄健宏)—— 深入理解 Redis 内部机制 - 《高性能 MySQL》(第 5 章:缓存策略) **文章**: - Martin Fowler: *Patterns of Distributed Systems* - Redis 官方文档:https://redis.io/docs/ - Google: *Designing a Cache System* **开源项目**: - Caffeine(Java 本地缓存) - Redisson(Java Redis 客户端,提供分布式锁等) - JetCache(阿里开源的多级缓存框架) --- ## 8. 名词速查表 (Glossary) | 名词 | 全称 | 解释 | | :--- | :--- | :--- | | **Cache** | - | **缓存**。存储数据副本的快速存储层,用于加速访问。 | | **Hit** | - | **缓存命中**。请求的数据在缓存中找到,无需访问数据库。 | | **Miss** | - | **缓存未命中**。请求的数据不在缓存中,需要回源查询。 | | **Hit Ratio** | - | **命中率**。缓存命中的请求数占总请求数的比例(目标: > 95%)。 | | **TTL** | Time To Live | **生存时间**。缓存条目的过期时间。 | | **Eviction** | - | **淘汰**。缓存满了时,删除旧数据为新数据腾空间。 | | **LRU** | Least Recently Used | **最近最少使用**。常见的缓存淘汰策略。 | | **LFU** | Least Frequently Used | **最不经常使用**。按访问频率淘汰的策略。 | | **Cache Penetration** | - | **缓存穿透**。查询不存在数据,导致请求直接打到数据库。 | | **Cache Breakdown** | - | **缓存击穿**。热点数据过期,瞬间大量请求打到数据库。 | | **Cache Avalanche** | - | **缓存雪崩**。大量缓存同时过期,数据库压力骤增。 | | **Bloom Filter** | - | **布隆过滤器**。空间效率高的概率型数据结构,用于判断元素是否可能存在。 | | **Cache-Aside** | - | **旁路缓存**。应用代码直接操作缓存和数据库的模式。 | | **Read-Through** | - | **读穿透**。缓存库自动从数据库加载数据。 | | **Write-Through** | - | **写穿透**。写入缓存时同步写入数据库。 | | **Write-Behind** | - | **异步写回**。写入缓存后异步批量写数据库。 | | **Local Cache** | - | **本地缓存**。与应用在同一进程内的缓存(如 Caffeine)。 | | **Distributed Cache** | - | **分布式缓存**。独立服务,通过网络访问(如 Redis)。 | | **Consistent Hashing** | - | **一致性哈希**。分布式缓存中用于数据分片和节点扩缩容的算法。 |