Skip to content

cache-aside-simulation ​

1. 实验目标 ​

用纯 Java CLI(无外部依赖)仿真 Cache-Aside 缓存五大经典场景(对应 docs/06-backend-data/07):

  1. Cache-Aside 读路径:读 Cache → Miss → 读 DB → 写回 Cache
  2. 缓存穿透:查不存在的 key 绕过缓存直击 DB(布隆过滤器/空值可拦截)
  3. 缓存击穿:热点 key 过期瞬间并发重建(互斥锁只让一个线程回源)
  4. 缓存雪崩:批量 key 同时过期 vs 随机 TTL 打散
  5. 双写一致性:先删缓存后更 DB 的窗口期不一致 vs 先更 DB 后删缓存

2. 工程要点 ​

  • CACHE(ConcurrentHashMap 模拟 Redis)+ DB(HashMap 模拟 MySQL)
  • dbHits 计数器量化"穿透到 DB 的次数",直观对比防护效果
  • getWithMutex:Double-Check + 单例锁,50 并发读热点 key 只回源 1 次
  • demoAvalanche:1000 个 key 固定 TTL 全部撞车 vs 随机 TTL 仅 2 个同时过期

3. 运行方式 ​

bash
cd labs/java/backend-data/cache-aside-simulation
javac -d out src/CacheAsideSimulation.java
java -cp out CacheAsideSimulation

(无需任何依赖,JDK 8+ 即可)

4. 预期现象 ​

场景输出要点
Cache-Asideuser:1 命中缓存,user:2 Miss 后回源并写回
穿透1000 次查询不存在 key → dbHits = 1000(全量打 DB)
击穿50 并发读热点 key(互斥锁)→ dbHits = 1
雪崩固定 TTL:1000/1000 同时过期;随机 TTL:2/1000
双写先删缓存:缓存旧值残留(不一致);先更 DB:缓存 Miss 下次回源新值

5. 常见误区 ​

误区实际情况
缓存一定能抗住高并发穿透/击穿/雪崩三类场景都会让流量直达 DB,需要布隆过滤器/互斥锁/随机 TTL
更新缓存比删除缓存好写频繁时更新缓存浪费计算;"删除缓存"懒加载更稳,但要处理窗口期(延迟双删)
击穿和穿透是一回事穿透查的是不存在 key;击穿是单个热点 key 过期瞬间的高并发回源

6. 对应知识库文档 ​

7. 完整源码 ​

站点构建时间:2026/8/24 23:43:17