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)。
Links