3种常用的缓存读写策略详解

大家好 我是积极向上的湘锅锅💪💪💪

希望小伙伴们秋招一起上岸👫👫👫

Cache Aside Pattern(旁路缓存模式)

Cache Aside Pattern(旁路缓存模式)是目前使用的最多的缓存模式,通常使用的场景是读多写少,比如用户信息,都是一旦写入缓存,几乎不会修改,但会出现数据不一致的情况

读:

  • 从缓存中读取数据,如果有,就直接返回
  • 如果没有读取到数据,就从数据库读取
  • 并写入到缓存中

写:

  • 先更新数据库
  • 然后直接删除缓存

那问题来了:

1. 为什么是删除缓存而不是修改缓存?

  • 更新缓存:每次更新都要更新缓存,无效写操作较多
  • 删除缓存:更新数据库的时候让缓存失效,只有再查询的时候再更新缓存

场景: 比如我要修改100次数据库
如果按照更新缓存的步骤,那我缓存就要更新100次,那之前的99次都是无效数据
如果我按照删除缓存,那只会删除一次,且查询的数据一定是最新的(数据一致性的情况下)

2. 那该如何保证缓存和数据库操作同时成功或者失败?

  • 单体系统:将缓存和数据库操作放在一个事务
  • 分布式系统:利用TCC等分布式方案

3. 先操作缓存还是先操作数据库?

  • 先删除缓存,再操作数据库
    线程1删除的时候,线程2读取数据库,此时数据还没更新
    可能会造成数据库(DB)和缓存(Cache)数据不一致的问题
    比如:

在这里插入图片描述

  • 先操作数据库再删除缓存
    恰好缓存失效,线程1开始更新,此时线程2因为找不到缓存,开始读取数据库,此时数据还未更新,所以也是一个旧值
    在这里插入图片描述
    理论上来说还是可能会出现数据不一致性的问题,不过概率非常小,因为缓存的写入速度是比数据库的写入速度快很多,一般是几ms,所以造成数据不一致需要几个条件:
  • 缓存刚好失效
  • 在写缓存的几ms内,其他线程读取数据库

所以综合来看,先操作数据库再删除缓存出现的数据不一致性可能性较小

最后再看下Cache Aside Pattern的缺陷:

  • 首次请求数据一定不在 cache 的问题:

解决: 对于热点数据,我们可以提前将数据放入缓存中,也就是缓存预热

  • 如果写操作比较多造成删除操作频繁的问题:

解决: 如果删除比较多,那就不执行删除

  1. 如果要求缓存数据一致性较强:更新DB的时候同样更新cache,不过需要加一个锁/分布式锁来保证更新cache的时候不存在线程安全问题
  2. 如果要求缓存数据一致性较弱:更新DB的时候同样更新cache,但是给缓存加一个比较短的过期时间,这样的话就可以保证即使数据不一致的话影响也比较小

Read/Write Through Pattern(读写穿透)

服务端将cache做为主要数据存储,也就是说所以对数据的增删查改操作都是在cache上操作,然后由cache负责读取和写入DB

写:

  • 先查cache,如果cache没有,直接更新DB
  • cache中存在,则先更新cache,然后由cache服务自己更新DB

读:

  • 从cache中读取数据,读取到就直接返回
  • 读取不到先从DB加载,写入到cache后返回

优点:因为程序只和缓存交互,编码会变得更加简单和整洁,当需要在多处复用相同逻辑时这点就变得格外明显,Write-Through的潜在使用场景是银行系统

缺点:因为这样可以理解为后端是单一存储,但一方面DB占据的是磁盘资源而cache是内存资源,所以要注意缓存有效性的管理,否则会导致大量的缓存占用内存资源


Write-Behind(异步缓存写入)

Write-Behind和Write-Through程序只和缓存打交道很相似,不过区别是Write-Through会把数据立即写入数据库中,而Write-Behind是通过异步的方式将数据持久化到数据库中

其中可以实现的效果就是可以批量或者定时的写入数据,极大的降低了请求延迟并减轻了数据库的负担

优点:

Write Behind Pattern 下 DB 的写性能非常高,非常适合一些数据经常变化又对数据一致性要求没那么高的场景,比如浏览量、点赞量

缺点:

当然这肯定会导致数据一致性问题,比如cache数据可能还没异步更新DB的话,cache服务可能就就挂掉了,所以会用到我们的消息队列来保证消息的可靠性

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

owensweat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值