Cache Aside Pattern(缓存模式)

2 篇文章 0 订阅

在一次秒杀系统中接触到这个概念--Cache Aside Pattern

度娘之后,说下我的理解:

为什么要用缓存模式:

提升服务性能!!!而服务性能瓶颈往往都在DB,高并发情况下尤甚,我们知道数据库是持久化在硬盘上,而缓存往往是基于内存的,两个之间的读写性能不在一个量级,由此可见缓存带来的性能提升。

什么时候需要使用缓存?

1>需要频繁的查询数据库

2>极其消耗数据库性能的数据

比如:用户余额查询,商品库存查询,商品销量排行榜。。。

缓存的读写操作:

读操作流程:

(1)读取缓存中是否有相关数据
(2)如果缓存中有相关数据,则返回【这就是所谓的数据命中“hit”】
(3)如果缓存中没有相关数据,则从数据库读取相关数据【这就是所谓的数据未命中“miss”】,放入缓存中,再返回
缓存的命中率 = 命中缓存请求个数/总缓存访问请求个数 = hit/(hit+miss)

写操作流程:

这里涉及到Cache Aside Pattern的几个讨论点:

1>“淘汰缓存”还是“更新缓存

毋庸置疑:淘汰缓存

什么是更新缓存:数据不但写入数据库,还会写入缓存
什么是淘汰缓存:数据只会写入数据库,不会写入缓存,只会把数据淘汰掉

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

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

(1)请求1先操作数据库,请求2后操作数据库

(2)请求2先set了缓存,请求1后set了缓存,导致,数据库与缓存之间的数据不一致。

若选择淘汰缓存,则只会增加一次Miss,不会产生脏读

2>缓存和数据库的操作时序

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

若先淘汰缓存再操作数据库:

在并发写时:

(1)写请求淘汰了缓存

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

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

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

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

(6)数据库主从同步完成

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

 

但是这里有个问题:

由于写数据库与淘汰缓存不能保证原子性,如果先操作数据库,再淘汰缓存,在原子性被破坏时:

(1)修改数据库成功了

(2)淘汰缓存失败了

还是会导致数据库与缓存的数据不一致。

究竟采用哪种时序呢?
对于一个不能保证事务性的操作,一定涉及“哪个任务先做,哪个任务后做”的问题,解决这个问题的方向是:
如果出现不一致,谁先做对业务的影响较小,就谁先执行

所以,在不考虑并发的情况下,应首先考虑原子性,先淘汰缓存,在更新数据库

不考虑原子性的情况,可能会有并发写,这时应该先更新数据库,再淘汰缓存!

 

 

 

 

 

ps:总结

 

1>应该淘汰缓存而不是更新缓存,更新缓存在并发的时候可能带来数据的不一致
2>cache aside pattern 建议先操作数据库,再淘汰缓存,这样可能会导致一种情况,A请求更改了数据库,此时还没有淘汰缓存,这时B读请求读了缓存,读取到的数据就是脏数据,直到A请求淘汰了缓存数据才是正确的
3>若是先淘汰缓存后更新数据库,会导致写请求A淘汰缓存还没有来得及更新数据库,此时B读请求读了缓存,发现缓存中没有数据就去数据库读取,此时读取到的是旧值,然后把旧值存到redis中,导致之后的读请求都会读取到脏数据
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值