Cache Aside

  • 失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。
  • 命中:应用程序从cache中取数据,取到后返回。
  • 更新:先把数据存到数据库中,成功后,再让缓存失效。
  • Cavet: 先读数据库,放数据到缓存前有另外写数据库,缓存中放的是老数据:脏数据。
    • 要么通过2PC或是Paxos协议保证一致性,要么就是拼命的降低并发时脏数据的概率,而Facebook使用了这个降低概率的玩法,因为2PC太慢,而Paxos太复杂。当然,最好还是为缓存设置上过期时间。

Read/Write Through

  • 把更新数据库(Repository)的操作由缓存自己代理了
  • 应用认为后端就是一个单一的存储,而存储自己维护自己的Cache
  • Read Through
    • 在查询操作中更新缓存
    • 当缓存失效的时候(过期或LRU换出)
      • Read Through则用缓存服务自己来加载,从而对应用方是透明的。
      • Cache Aside是由调用方负责把数据加载入缓存,
  • Write Through
    • 如果没有命中缓存,直接更新数据库,然后返回。
    • 如果命中了缓存,则更新缓存,然后再由Cache自己更新数据库(这是一个同步操作)

Write Behind Caching

缓存击穿

  • 现象:某个非常热点的 key 刚好失效(过期/被删),大量并发同时 miss,瞬间都去打 DB。
  • 范围:通常是单个或少数热点 key
  • 典型信号:某个接口/某个 key 的 QPS 爆炸,DB 读被同一类查询打满。
  • 常见治理
    • singleflight / 互斥锁 lease:同一 key 只允许一个请求回源,其它等结果

缓存雪崩

  • 现象:大量 key 在同一时间窗口同时过期/缓存集群故障,导致大量请求同时 miss,DB 被“洪峰”冲垮。
  • 范围:通常是一大片 key 或整个缓存层
  • 常见触发
    • 批量设置了相同 TTL(如整点过期)。
    • 缓存节点宕机/网络分区/集群重启。
    • 缓存容量不够导致大面积淘汰(eviction storm)。