缓存常用的3种读写策略

Cache Aside Pattern(旁路缓存模式)

Cache Aside Pattern 是我们平时使用比较多的一个缓存读写模式,比较适合读请求比较多的场景。
Cache Aside Pattern 中服务端需要同时维系 DB 和 cache,并且是以 DB 的结果为准。

  • 先更新 DB

  • 然后直接删除 cache 。、

  • 写的过程
    :

  • 从 cache 中读取数据,读取到就直接返回

  • cache中读取不到的话,就从 DB 中读取数据返回

  • 再把数据放到 cache 中。

  • 读的过程
    那么在写数据的过程中,可以先删除 cache ,后更新 DB 么?
    答案: 那肯定是不行的!因为这样可能会造成数据库(DB)和缓存(Cache)数据不一致的问题。为什么呢?比如说请求1 先写数据A,请求2随后读数据A的话就很有可能产生数据不一致性的问题:请求1先把cache中的A数据删除(此时DB中还有旧数据) -> 请求2从DB中读取(旧)数据->请求1再把DB中的A数据更新(这样明明请求1比请求2先操作,结果请求2反而读取到了请求1更新之前的旧数据)。

那么在写数据的过程中,先更新DB,后删除cache就没有问题了么?
答案: 理论上来说还是可能会出现数据不一致性的问题,不过概率非常小,因为缓存的写入速度是比数据库的写入速度快很多!
比如请求1先读数据 A,请求2随后写数据A,并且数据A不在缓存中的话也有可能产生数据不一致性的问题:请求1从DB读(旧)数据A(数据A还不在缓存中,此时读到的(旧)数据A应该写入缓存,因为写入缓存速度很快,所以基本上不会像这样被请求2的写数据库插进来)->请求2写更新(新)数据 A 到数据库并删除cache中的(旧)A数据->请求1将(旧)数据A写入cache。(如此数据库中是新数据A而缓存中是旧数据A,这样下次读取的时候从缓存读到的A就是跟数据库里的A是不一致的)。

Cache Aside Pattern 的缺陷

缺陷1:首次请求数据一定不在 cache 的问题
解决办法:可以将热点数据可以提前放入cache 中。

缺陷2:写操作比较频繁的话导致cache中的数据会被频繁被删除,这样会影响缓存命中率 。
解决办法:

  • 数据库和缓存数据强一致场景 :更新DB的时候同样更新cache,不过我们需要加一个锁/分布式锁来保证更新cache的时候不存在线程安全问题(是说更新cache的时候,数据库里的数据又被其他线程修改了,导致数据库与缓存不一致)。
  • 可以短暂地允许数据库和缓存数据不一致的场景 :更新DB的时候同样更新cache,但是给缓存加一个比较短的过期时间,这样的话就可以保证即使数据不一致的话影响也比较小(似乎不是个好办法,如果更新和读取之间的时间间隔很小的话似乎会出很多错?)。

Read/Write Through Pattern(读写穿透)

Read/Write Through Pattern 中服务端把 cache 视为主要数据存储,从中读取数据并将数据写入其中。cache 服务负责将此数据读取和写入 DB,从而减轻了应用程序的职责。
这种缓存读写策略小伙伴们应该也发现了在平时在开发过程中非常少见。抛去性能方面的影响,大概率是因为我们经常使用的分布式缓存 Redis 并没有提供 cache 将数据写入DB的功能

写(Write Through):

  • 先查 cache,cache 中不存在,直接更新 DB。

  • cache 中存在,则先更新 cache,然后 cache 服务(cache来更新DB啊)自己更新 DB(同步更新 cache 和 DB)。

  • 在这里插入图片描述
    读(Read Through):

  • 从 cache 中读取数据,读取到就直接返回 。

  • 读取不到的话,先从 DB 加载(到缓存),写入到 cache 后(从缓存)返回响应。

  • 在这里插入图片描述
    Read-Through Pattern 实际只是在 Cache-Aside Pattern 之上进行了封装。在 Cache-Aside Pattern 下,发生读请求的时候,如果 cache 中不存在对应的数据,是由客户端(从数据库读取了数据,再把读取到的数据写入缓存)负责把数据写入 cache(缓存),而 Read Through Pattern 则是 cache 服务(cache服务?是指cache服务进程把数据从DB加载到缓存?然后客户端再从缓存读取数据)自己来写入缓存的,这对客户端是透明(透明好像是指客户端看不到这个过程,黑盒子的意思吧?这个透明的概念太坑了)的。(反正这个策略基本不用)

Write Behind Pattern(异步缓存写入)

Write Behind Pattern 和 Read/Write Through Pattern 很相似,两者都是由 cache 服务来负责 cache 和 DB 的读写。
两个又有很大的不同:**Read/Write Through 是同步更新 cache 和 DB,而 Write Behind Caching 则是只更新缓存,不直接更新 DB,而是改为异步批量(是说缓存更新了足够多了再一批更新到DB?)的方式来更新 DB。**这种方式对数据一致性带来了更大的挑战,比如cache数据可能还没异步更新DB的话,cache服务可能就就挂掉了(所以整个过程就是DB中根本没存过缓存里的数据)。

这种策略在我们平时开发过程中也非常非常少见,但是不代表它的应用场景少,比如消息队列中消息的异步写入磁盘、MySQL 的 InnoDB Buffer Pool 机制都用到了这种策略。Write Behind Pattern 下 DB 的写性能非常高,非常适合一些数据经常变化又对数据一致性要求没那么高的场景,比如浏览量、点赞量。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值