31

Cache Aside Pattern(缓存模式)解析

 5 years ago
source link: http://zhuanlan.51cto.com/art/201807/578829.htm?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在《 究竟先操作缓存,还是数据库? 》,有同学在评论提出,相关方案违背了“Cache Aside Pattern”的原则,故今天聊一聊Cache Aside Pattern。

26Fve2V.jpg!web

另外,在讨论技术方案时,尽量不说:

  • “你是错的,应该怎么样”
  • “facebook不是这样,所以你是错的”

画外音:凭什么facebook就是真理?它的方案只是适合它的业务而已。

说明适用场景,说明来龙去脉,说明前因后果,比具体使用什么方案更重要。

什么是“Cache Aside Pattern”?

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

对于读请求

  • 先读cache,再读db
  • 如果,cache hit,则直接返回数据
  • 如果,cache miss,则访问db,并将数据set回缓存

IrEZnqb.jpg!web

如上图:

  • 先从cache中尝试get数据,结果miss了
  • 再从db中读取数据,从库,读写分离
  • 最后把数据set回cache,方便下次读命中

画外音:这一点上,与《究竟先操作缓存,还是数据库?》说的是一致的。

对于写请求

  • 淘汰缓存,而不是更新缓存
  • 先操作数据库,再淘汰缓存

2mYVvuU.jpg!web

如上图:

(1)第一步要操作数据库,第二步操作缓存

画外音:这一点上,与《究竟先操作缓存,还是数据库?》说的不一致,也是评论反驳比较激烈的地方。

(2)缓存,采用delete淘汰,而不是set更新

画外音:这一点上,与《缓存,究竟是淘汰,还是修改?》说的是一致的。

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

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

neeINzf.jpg!web

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

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

  • 请求1先操作数据库,请求2后操作数据库
  • 请求2先set了缓存,请求1后set了缓存

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

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

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

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

6VVnUvq.jpg!web

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

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

  • 写请求淘汰了缓存
  • 写请求操作了数据库(主从同步没有完成)
  • 读请求读了缓存(cache miss)
  • 读请求读了从库(读了一个旧数据)
  • 读请求set回缓存(set了一个旧数据)
  • 数据库主从同步完成

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

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

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

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

  • 修改数据库成功了
  • 淘汰缓存失败了

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

如何解决这类问题呢?

答:详见《 究竟先操作缓存,还是数据库? 》。

【本文为51CTO专栏作者“58沈剑”原创稿件,转载请联系原作者】

mU3aa2E.jpg!web

戳这里,看该作者更多好文


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK