Cache Aside Pattern
Cache Aside Pattern 是由 facebook 提出的一个广受认可的缓存方案,核心操作有两点:
- 读请求:先读缓存,如果命中缓存,直接返回结果;否则,访问数据库,并更新缓存;
- 写请求:先更新数据库,再置缓存失效;
对于写请求为何是置缓存失效,而不是更新缓存?
设想如果将写请求改为先更新数据库,再更新缓存,如果有 A/B 两个请求同时写,由于无法保证时序,可能会出现下面的操作过程,导致数据库和缓存不一致:
- A 更新数据库
- B 更新数据库
- B 更新缓存
- A 更新缓存
但实际上,即使先更新数据库,再置缓存失效,也有可能会出现不一致的情况,譬如 A 为读请求,B 为写请求:
- A 读缓存不命中,读数据库旧值
- B 写数据库为新值
- B 设置缓存失效
- A 更新缓存为旧值
此时,缓存的数据为旧值,但这种场景发生的概率非常小。因为这个需要发生在读缓存时缓存失效,而且并发着一个写操作。实际上数据库的写操作比读操作慢得多,还要锁表;而读操作必须在写操作前进入数据库操作,并且晚于写操作更新缓存。这些条件都具备的概率不大。
另外,有一些复杂的缓存场景,缓存数据不是简单地从数据库里直接读取出来的,可能需要 join 其他表进行复杂的计算,如果更新很频繁,缓存也会被不必要地频繁更新。