详解Redis的三种常用的缓存读写策略步骤


Posted in Redis onMay 06, 2022

一、Redis三种常用的缓存读写策略

Redis有三种读写策略分别是:旁路缓存模式策略、读写穿透策略、异步缓存写入策略。

这三种缓存读写策略各有优势,不存在最佳,需要我们根据实际的业务场景选择最合适的。

二、旁路缓存模式(Cache Aside Pattern)

旁路缓存模式是我们平时使用比较多的一个缓存读写模式,比较适合读请求比较多的场景。

旁路缓存模式中服务端需要同时维护DBCache,并且是以DB的结果为准。

读写步骤

写:

  • 先更新DB
  • 然后直接删除cache

如下图:

详解Redis的三种常用的缓存读写策略步骤

读:

  • cache中读取数据,读取到就直接返回。
  • cache中读取不到的话,就从DB读取返回。
  • 再把数据写到cache中。

如下图:

详解Redis的三种常用的缓存读写策略步骤

自我思考

思考这样子的一个问题:“如果在写数据的过程中,可以先删除cache,再更新DB吗?

答案: 答案肯定是不行的,因为这样子可能造成数据库和缓存数据不一致的问题,比如这个时候有一个数据在DB和缓存都为100,请求1需要将这个数据更新写成200,如果先删除换出再更新数据库的话,在请求1已经删除缓存但是数据库还没写完的时候,有一个请求2读取数据,首先去缓存读取,发现缓存被删除了,然后去数据库读取得到100(这个时候请求1还没写完)再写入缓存,这个时候请求1写完了,这个时候数据库里数据为200,缓存里为100,不一致。

可以简单描述为:

请求1先把cache中的数据删除 -> 请求2从DB中读取数据 -> 请求1再把DB中的数据更新

紧接着思考:“在写数据的过程中,如果先写BD,再删除cache就不会造成数据不一致了吗?

答案: 理论上来说还是会出现数据不一致的问题,不过概率很小,因为缓存的写入速度是比数据库写入速度快很多。

比如请求1先读数据A,请求2随后写数据A,并且数据A不在缓存中存在的话就会去数据库读取,读取完请求2再更新完并删除缓存,然后请求1把数据A写入缓存,这个时候数据库和缓存就不一致了。

这个过程可以简单的描述为:

请求1从DB读取数据A -> 请求2写更新数据A到数据库再删除cache中的A数据 -> 请求1将数据A写入缓存

缺点

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

    解决办法:可以将热点数据提前写入cache中。

  • 写操作比较频繁的话导致cache中的数据会被频繁的删除,这样会影响缓存命中率。

    解决办法:

    • 数据库和缓存强一直场景:更新DB的时候同样更新cache,不过需要加一个锁/分布式锁来保证更新cache的时候不存在线程安全问题。
    • 可以短暂的允许数据库和缓存数据不一致的场景:更新DB的时候同样更新cache,但是给缓存加一个比较短的过期时间,这样的话就可以保证即使数据不一致的话影响也比较小。

三、读写穿透(Read/Write Through Pattern)

读写穿透中服务端把cache视为主要数据存储,从中读取数据并将数据写入其中。cache服务负责将此数据读取和写入DB,从而减轻应用程序的职责。

读写步骤

写:

  • 先查cachecache中不存在,直接更新DB
  • cache中存在,则先更新cache,然后cache服务自己更新DB(同时更新DBcache)。

如下图:

详解Redis的三种常用的缓存读写策略步骤

读:

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

如下图:

详解Redis的三种常用的缓存读写策略步骤

读写穿透实际是在旁路缓存之上进行了封装。在旁路缓存下,发生读请求的时候,如果cache中不存在对应的数据,是由客户端自己负责把数据写入cache,而读写穿透则是cache服务自己来写入缓存,这对客户端是透明的。

和旁路缓存一样,读写穿透也存在首次请求数据一定不在cache中的问题,对于热点数据可以提前写入缓存中。

四、异步缓存写入(Write Behind Pattern)

异步缓存写入和读写穿透很相似,两者都是由cache服务来负责cacheDB的读写。

两者最大的不同点就是:读写穿透是同步更新DBcache,而异步缓存写入则是只更新cache,不直接更新DB,而是改为异步批量的方式更新DB

很明显,这种方式对数据一致性带来了更大的挑战,比如cache数据可能还没异步更新DBcache服务可能就挂了。

这种策略在我们平时开发过程中也非常少见,但是不代表它的应用场景少,比如消息队列中消息的异步写入磁盘、MySQLInnoDB Buffer Pool机制都用到了这种策略。

异步缓存写入的写性能非常高,非常适合写数据经常变化又对数据一致性要求没那么高的场景下使用,比如浏览量、点赞量等。

参考:javaguide.cn/database/re…

到此这篇关于详解Redis的三种常用的缓存读写策略步骤的文章就介绍到这了!


Tags in this post...

Redis 相关文章推荐
redis连接被拒绝的解决方案
Apr 12 Redis
详解RedisTemplate下Redis分布式锁引发的系列问题
Apr 27 Redis
深入浅析Redis 集群伸缩原理
May 15 Redis
分布式锁为什么要选择Zookeeper而不是Redis?看完这篇你就明白了
May 21 Redis
redis cluster支持pipeline的实现思路
Jun 23 Redis
redis不能访问本机真实ip地址的解决方案
Jul 07 Redis
面试分析分布式架构Redis热点key大Value解决方案
Mar 13 Redis
Redis高可用集群redis-cluster详解
Mar 20 Redis
Redis基本数据类型Set常用操作命令
Jun 01 Redis
Redis实现短信验证码登录的示例代码
Jun 14 Redis
使用Redis实现分布式锁的方法
Jun 16 Redis
Redis sentinel哨兵集群的实现步骤
Jul 15 Redis
windows安装 redis 6.2.6最新步骤详解
muduo TcpServer模块源码分析
Redis数据同步之redis shake的实现方法
Apr 21 #Redis
Grafana可视化监控系统结合SpringBoot使用
Redis官方可视化工具RedisInsight安装使用教程
Redis实现一个账号只能登录一个设备
Apr 19 #Redis
Redis如何实现验证码发送 以及限制每日发送次数
Apr 18 #Redis
You might like
模板引擎正则表达式调试小技巧
2011/07/20 PHP
PHP生成数组再传给js的方法
2014/08/07 PHP
PHP 生成微信红包代码简单
2016/03/25 PHP
使用php实现从身份证中提取生日
2016/05/09 PHP
thinkPHP3.x常量整理(预定义常量/路径常量/系统常量)
2016/05/20 PHP
php字符串的替换,分割和连接方法
2016/05/23 PHP
php 实现Hash表功能实例详解
2016/11/29 PHP
PHP 传输会话curl函数的实例详解
2017/09/12 PHP
php 实现银联商务H5支付的示例代码
2019/10/12 PHP
js 跨域和ajax 跨域问题小结
2009/07/01 Javascript
利用jquery操作select下拉列表框的代码
2010/06/04 Javascript
javascript forEach通用循环遍历方法
2010/10/11 Javascript
jquery获得页面元素的坐标值实现思路及代码
2013/04/15 Javascript
JavaScript中String.prototype用法实例
2015/05/20 Javascript
js表单处理中单选、多选、选择框值的获取及表单的序列化
2016/03/08 Javascript
当jquery ajax遇上401请求的解决方法
2016/05/19 Javascript
详解Angular路由 ng-route和ui-router的区别
2017/05/22 Javascript
EasyUI实现下拉框多选功能
2017/11/07 Javascript
超好用的jQuery分页插件jpaginate用法示例【附源码下载】
2018/12/06 jQuery
javascript 使用sleep函数的常见方法详解
2020/04/26 Javascript
JS实现电脑虚拟键盘的操作
2020/06/24 Javascript
[01:04:09]DOTA2-DPC中国联赛 正赛 iG vs VG BO3 第二场 2月2日
2021/03/11 DOTA
python目录与文件名操作例子
2016/08/28 Python
利用python将xml文件解析成html文件的实现方法
2017/12/22 Python
Django rest framework基本介绍与代码示例
2018/01/26 Python
Python微医挂号网医生数据抓取
2019/01/24 Python
为什么从Python 3.6开始字典有序并效率更高
2019/07/15 Python
python socket通信编程实现文件上传代码实例
2019/12/14 Python
Python 读取xml数据,cv2裁剪图片实例
2020/03/10 Python
python进行OpenCV实战之画图(直线、矩形、圆形)
2020/08/27 Python
英国在线房屋中介网站:Yopa
2018/01/09 全球购物
Omio葡萄牙:全欧洲低价大巴、火车和航班搜索和比价
2019/02/09 全球购物
乌克兰电子和家用电器商店:Foxtrot
2019/07/23 全球购物
在对linux系统分区进行格式化时需要对磁盘簇(或i节点密度)的大小进行选择,请说明选择的原则
2012/01/13 面试题
实验室安全管理制度
2015/08/05 职场文书
联想win10摄像头打不开怎么办?win10笔记本摄像头打不开解决办法
2022/04/08 数码科技