Cache Aside Pattern:旁路缓存的行业最佳实践(4/14)

读实践、写实践、两个为什么——固化下来的模式,照着用就完了

缓存实践第 4 课封面:缓存架构与实践04:Cache Aside Pattern:旁路缓存的行业最佳实践

读实践、写实践、两个为什么——固化下来的模式,照着用就完了

《缓存架构与实践》第 4 篇:Cache Aside Pattern,旁路缓存的行业最佳实践。

有不少朋友问我,缓存到底怎么操作?

有些成熟的技术方案,用不着创新,固化下来的模式(pattern),学就完了。Cache Aside Pattern 就是旁路缓存的行业最佳实践。大部分情况下,照着用就完了。

什么是“Cache Aside Pattern”?

旁路缓存方案的经验实践,这个实践又分读实践,写实践。

与旁路缓存对应的,是穿透缓存。

读实践是怎么样的?

对于读请求:

Cache Aside Pattern 读实践流程:get 缓存 → 未命中读库 → set 回缓存

1. 先读cache,再读db;

2. 如果,cache hit,则直接返回数据;

3. 如果,cache miss,则访问db,并将数据set回缓存;

写实践是怎么样的?

对于写请求:

Cache Aside Pattern 写实践流程:write DB → del 缓存

1. 淘汰缓存,而不是更新缓存;

2. 先操作数据库,再淘汰缓存;

Cache Aside Pattern为什么建议淘汰缓存,而不是更新缓存?

如果更新缓存,在并发写时,可能出现数据不一致。

并发写时 set 缓存导致数据不一致(why not set cache)

如上图所示,如果采用set缓存。

在1和2两个并发写发生时,由于无法保证时序,此时不管先操作缓存还是先操作数据库,都可能出现:

1. 请求1先操作数据库,请求2后操作数据库;

2. 请求2先set了缓存,请求1后set了缓存;

导致,数据库与缓存之间的数据不一致。

所以,Cache Aside Pattern建议,delete缓存,而不是set缓存。

Cache Aside Pattern为什么建议先操作数据库,再操作缓存?

如果先操作缓存,在读写并发时,可能出现数据不一致。

读写并发时先操作缓存导致数据不一致:why not op db first

如上图所示,如果先操作缓存。

在1和2并发读写发生时,由于无法保证时序,可能出现:

1. 写请求淘汰了缓存;

2. 写请求操作了数据库(主从同步没有完成);

3. 读请求读了缓存(cache miss);

4. 读请求读了从库(读了一个旧数据);

5. 读请求set回缓存(set了一个旧数据);

6. 数据库主从同步完成;

导致,数据库与缓存的数据不一致。

所以,Cache Aside Pattern建议,先操作数据库,再操作缓存。

Cache Aside Pattern方案存在什么问题?

如果先操作数据库,再淘汰缓存,在原子性被破坏时:

1. 修改数据库成功了;

2. 淘汰缓存失败了;

导致,数据库与缓存的数据不一致。

Cache Aside Pattern总结

对于读请求:

1. 先读cache,再读db;

2. 如果,cache hit,则直接返回数据;

3. 如果,cache miss,则访问db,并将数据set回缓存;

对于写请求:

1. 淘汰缓存,而不是更新缓存;

2. 先操作数据库,再淘汰缓存;

潜在问题:

写操作原子性被破坏时,数据库与缓存的数据不一致。

检验一下

检索练习 · 读实践
Cache Aside Pattern 的读实践,cache miss 时怎么处理?

检索练习 · 写实践
Cache Aside Pattern 的写实践是哪两条?

检索练习 · 为什么淘汰而非更新
为什么建议 delete 缓存而不是 set 缓存?

检索练习 · 潜在问题
Cache Aside Pattern 方案的潜在问题是什么?

先操作数据库再淘汰缓存,还留着一个原子性破坏的口子;主从延时也可能把旧数据读进缓存。第 5 篇,看缓存双淘汰怎么把这两类不一致堵上。

知其然,知其所以然。思路比结论更重要。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

京ICP备2025137728号-3