老张聊架构 发表于 2021-8-11 20:40:00

先操作缓存,照旧数据库?这个问题Facebook也没办理...

读写数据时,应该先操作缓存,还是先操作数据库呢?这个简单的问题,回答起来并不简单...


https://p5.toutiaoimg.com/large/pgc-image/18145925bc0d49e0bb9d0cf5ce67d424
关于 数据库 + 缓存 的读写模式,业内较广泛承认的是Facebook提出的模式:Cache Aside Pattern。
https://p26.toutiaoimg.com/large/pgc-image/077abe773eb5420f8dd588e15d45e2d4
对于读请求
这个根本没啥疑问,标准流程如下:

[*]先读cache,再读db
[*]如果cache hit,则直接返回数据
[*]如果cache miss,则访问db,并将数据set回缓存
https://p6.toutiaoimg.com/large/pgc-image/44551c0e0679423995a225b79c8e6e2b
对于写请求
Cache Aside Pattern建议:
(1)淘汰缓存,而不是更新缓存
(2)先操作数据库,再淘汰缓存
为什么建议淘汰缓存,而不是更新缓存?
如果更新缓存,在并发写时,大概出现数据不一致。
https://p26.toutiaoimg.com/large/pgc-image/ed801c0dc4554ab4925dff808906490c
如上图所示,1和2同时发起写请求,1要将数据修改为a,2要将数据修改为b,由于无法包管时序,此时大概出现:
(1)请求1先操作数据库,请求2后操作数据库,数据库终极内容为b
(2)请求2先更新了缓存,请求1后更新缓存,缓冲终极内容为a
数据库与缓存之间的数据不一致。
所以,Cache Aside Pattern建议,淘汰缓存,而不是更新缓存。
为什么建议先操作数据库,再操作缓存?
如果先操作缓存,在读写并发时,大概出现数据不一致。
https://p26.toutiaoimg.com/large/pgc-image/3d5e0950dbaf4de7b8a255249e2e589f
如上图所示,在1和2并发请求,1修改数据,2读取数据。如果先操作缓存,由于无法包管时序,大概出现:
(1)写请求淘汰了缓存
(2)写请求操作了数据库(主从同步没有完成)
(3)读请求读了缓存(cache miss)
(4)读请求读了从库(读了一个旧数据)
(5)读请求set回缓存(set了一个旧数据)
(6)数据库主从同步完成
导致,数据库与缓存的数据不一致。
所以,Cache Aside Pattern建议,先操作数据库,再操作缓存。
Cache Aside Pattern方案存在什么问题?
如果先操作数据库,再淘汰缓存,大概出现:
(1)修改数据库成功了
(2)淘汰缓存失败了
导致,数据库与缓存的数据不一致。
https://p26.toutiaoimg.com/large/pgc-image/9c80223676ec487ca1dc4c2261bf8cdc
<hr>关注【老张聊架构】,前迅雷大数据CTO,带你成为百万年薪架构师!
页: [1]
查看完整版本: 先操作缓存,照旧数据库?这个问题Facebook也没办理...