Redis三种常见的缓存更新模式介绍

Redis常见的缓存更新策略有三种,分别是Cache Aside Pattern(旁路缓存模式)、Read/Write Through Pattern(读写穿透模式)以及Write Behind Pattern (异步缓存写入模式)三种。三种模式各有优劣,不存在最佳模式,根据具体的业务场景选择适合自己的缓存读写模式即可。以下将分别介绍三种模式。

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

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

下面我们来看一下这个策略模式下的缓存读写步骤。

写:

  1. 先更新db;
  2. 直接删除cache。

如下图所示:


读:

  1. 从cache中读取数据,读取到就直接返回;
  2. cache中读取不到的话,就从db中读取数据返回;
  3. 再把db中读取到的数据放到cache中。

如下图所示:

那么问题来了,为什么是删除cache,而不是更新cache呢?

主要原因有两点:

  1. 对服务端资源造成浪费: 删除cache更加直接,这是因为cache中存放的一些数据需要服务端经过大量的计算才能得出,会小号服务端的紫东苑,是一笔不小的开销。如果频繁修改db, 就可能会导致需要频繁更新cache,二cache中的数据可能都没有被反问到。
  2. 产生数据不一致的问题: 并发场景下,更新cache产生数据不一致性问题的概率会更大。

然后另外一个问题, 在写数据的过程中,能否先删除cache,后更新db呢?

答案可能是不行,因为这样可能会导致造成数据库(db)和缓存(Cache)数据不一致的问题。

举个例子:请求1先写数据A,请求2虽有读数据A的话,就很有可能产生数据不一致性的问题。这个过程可以简单描述为:

  1. 请求1先把cache中的A数据删除;
  2. 请求2从db中读取数据;
  3. 请求1再把db中的A数据更新;

这就会导致请求2读取到的是旧值。

那么 如果是在写数据的过程中,先更新db,后删除cache就没有问题了吗

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

举个例子:请求1先读取数据A,请求2随后写数据A,并且数据A在请求1请求之前不在缓存中的话,也有可能产生数据不一致性的问题。这个过程可以简单描述为:

  1. 请求1从db读取数据A;
  2. 请求2更新db中的数据A(此时缓存中无数据A,故不用执行删除缓存操作);
  3. 请求1将数据A写入cache。

这就会导致cache中存放的其实是旧值。

现在我们再来分析一下 Cache Aside Pattern 的缺陷。

缺陷1:首次请求数据一定不在cache的问题

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

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

解决方法:

  • 数据库和缓存数据强一致场景 :更新 db 的时候同样更新 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服务自己更新db(同步更新cache和db)

如下图:

读(Read Through):

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

如下图:

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

和 Cache Aside Pattern 一样, Read-Through Pattern 也有首次请求数据一定不再 cache 的问题,对于热点数据可以提前放入缓存中。

Write Behind Pattern (异步缓存写入模式)

Write Behind Pattern 和 Read/Write Through Pattern 很相似,两者都是由 cache 服务来负责 cache 和 db 的读写。

但是,两个又有很大的不同:Read/Write Through 是同步更新 cache 和 db,而 Write Behind 则是只更新缓存,不直接更新 db,而是改为异步批量的方式来更新 db。

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

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

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

以上便是对Redis常见的三种缓存更新策略的一个介绍。

Redis-缓存更新策略相关推荐

  1. 【Redis】缓存更新策略

    1. 缓存更新策略综述 内存淘汰 不用自己维护,利用 Redis 自己的内存淘汰机制 (内存不足时,触发策略,默认开启,可自己配置),其可在一定程度上保持数据一致性 超时剔除 给数据添加 TTL,到期 ...

  2. Redis的缓存更新策略

    文章目录 1.redis的缓存更新的三种策略 1.1 内存淘汰 1.2 超时剔除 1.3 主动更新 2. 缓存更新策略的最佳实践方案: 缓存的更新是redis为了节约内存而设计出来的东西,主要是因为内 ...

  3. Redis:缓存一致性问题(缓存更新策略)

    Redis缓存的一致性 1. 缓存 1.1 缓存的作用: 1.2 缓存的成本: 2. 缓存模型 3. 缓存一致性问题 3.1 引入 3.2 解决 (1) 主动更新:先更新数据库,再手动删除缓存 (2) ...

  4. Redis缓存过期策略

    转载出处链接 一.背景 线上你写代码的时候,想当然的认为写进 redis 的数据就一定会存在,后面导致系统各种 bug,谁来负责? 常见的有两个问题: 往 redis 写入的数据怎么没了? 可能有同学 ...

  5. 掌握分布式环境缓存更新策略,提高缓存与数据库双写一致性!

    概述 随着时代的发展,服务系统架构也已经由最初的单体架构转变为分布式.微服务架构模式. 从数据体量上来看,各系统存储的数据量越来越大,数据的查询性能越来越低. 此时,就需要我们不断的进行优化,最常用的 ...

  6. Redis 缓存删除策略

    Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言 ...

  7. Redis缓存失效策略思考

    1 删除过期数据 我们设置Redis元素时可以指定过期时间,那么Redis如何删除这些超时元素?Redis采用了两种策略:定期删除和惰性删除. (1) 定期删除 Redis每隔一段时间就检查哪些KEY ...

  8. redis缓存清除策略 、获取dumb.rdb或者***.aof文件的位置

    redis缓存清除策略 获取dumb.rdb或者***.aof文件的位置

  9. Redis缓存淘汰策略

    文章目录 noeviction allkeys-lru allkeys-lfu volatile-lru volatile-lfu allkeys-random volatile-random vol ...

  10. 说说 Redis 缓存删除策略

    Redis 缓存删除策略分为定时删除.定期删除与惰性删除.前两个是主动删除,后一个是被动删除. 1 定时删除 为 key 设置一个过期时间,时间一到,由定时器任务删除这个 key. 优点:节省内存,因 ...

最新文章

  1. GPU 加速下的图像视觉
  2. kafka streams_Kafka REST Proxy for MapR Streams入门
  3. js 数组 ajax php,js里面的对象ajax post到php端直接变成数组了?
  4. 一个从华为离职的朋友
  5. 实战四 win2008 r2 AD中大批量添加用户账号
  6. Python使用socket读取网页源代码实现简单爬虫程序
  7. 蓝牙学习笔记(九)——BLE超过20字节数据包传输(MTU)
  8. deeplearning 源码收集
  9. Excel如何删除表格中的空白列
  10. 机器学习中的数据不平衡解决方案大全
  11. js正则 保留一位小数或者两位小数
  12. Infectious Media Generator失败
  13. 【阿里巴巴矢量图库搭建一个属于自己的字体图标库iconfont】
  14. 网页在线视频播放大全
  15. macos 系统固件 路径_iTunes下载的固件在哪里?iTunes固件文件路径详解
  16. 入行游戏建模,做场景建模师必备软件有哪些?有无发展前景
  17. jmeter基础之保存响应数据到文件
  18. iOS中ImageIO框架详解与应用分析
  19. 爱阅书香之书源制作 POST请求方式
  20. 智能优化算法——粒子群算法原理(附代码)

热门文章

  1. 科普篇|什么是JBOD?
  2. redhat linux 6.4,redhat linux 6.4 运行 runcluvfy 错误一例
  3. AndroidStudio的几个个性的配置和个人笔记
  4. 进销存源码下载 mysql_java 进销存管理源码(含mysql脚本)
  5. 小票智能审核项目总结介绍
  6. 百度地图web API定位不准,定位偏移问题处理
  7. 2.ADS操作入门_线性/非线性仿真工具
  8. hyperapp 共享_Hyperapp快速入门
  9. windows下用Python把pdf文件转化为图片
  10. 《世界历史》学习记录