当前位置:首页 > 单片机 > 架构师社区
[导读]   作者:z小赵 ★  一枚用心坚持写原创的“无趣”程序猿,在自身受益的同时也让朋友们在技术上有所提升。 前面利用 6 篇文章讲述了 Redis 相关的基础知识,相信小伙伴们对 Redis 已经有了一个比较深入的认识和理解了;本文来讲讲实际生产环境中 Redis 作为常


  
Redis系列(七):缓存只是读写回种这么简单吗?如果是,那么请你一定看看这篇文章!

作者:z小赵

 

一枚用心坚持写原创的“无趣”程序猿,在自身受益的同时也让朋友们在技术上有所提升。


前面利用 6 篇文章讲述了 Redis 相关的基础知识,相信小伙伴们对 Redis 已经有了一个比较深入的认识和理解了;本文来讲讲实际生产环境中 Redis 作为常用缓存组件是怎么和 DB(关系型数据库,比如 MySQL)配合使用的。

看到这里可能有些朋友会内心肯定会淡淡的说上一句:写操作先更新 DB,然后在更新缓存,读操作先读缓存,如果没有读 DB 回种缓存,然后返回结果不就完事了么,这有什么好讲的?

只要你有这样的疑问,那么请你一定认真看完本文,因为缓存读写策略远不止你想的那么简单,下面我们就来分析一下几种常用的缓存读写方案,看看哪种更适合你。

读写缓存策略一

Redis系列(七):缓存只是读写回种这么简单吗?如果是,那么请你一定看看这篇文章!

如上图所示,对于写操作,先写 DB,如果 DB 成功,则同步写入缓存;对于读操作,首先从缓存中读取,若缓存未命中,则从 DB 中获取,如果取到了结果,将结果回种缓存并返回,若 DB 中也没有结果,则在缓存中设置一个短暂带有过期时间的空值,防止相同 key 频繁请求对 DB 造成大量的无效请求。

策略一优缺点对比

  • 优点

  1. 缓存读写策略简单(在很多读多写少的场景中,此种策略使用的频率还是很高的)。
  2. 不需要依赖其他第三方缓存组件协同完成。
  • 缺点

  • Redis系列(七):缓存只是读写回种这么简单吗?如果是,那么请你一定看看这篇文章!

    举个例子,如上图所示,假设两条线程 1 和线程 2 同时对一件特价商品进行价格调整,假设商品初始状态为 20 元,线程 1 将其价格修改为 19 元并写入缓存,然后线程 2 将商品的价格修改为 18 元,此时线程 A 进行读取操作,因为线程 2 还没来得及将缓存数据修改为 18,所以此时线程 1 拿到的价格为 19 元,但是此时库里的价格却是 18 元。从这个例子可以看出,对于进行频繁修改的数据,使用此种缓存读写策略显然是不合理的。针对这种缓存读写方案的缺陷,我们来看看下一种缓存读写策略。

    Cache Aside 读写策略

    Redis系列(七):缓存只是读写回种这么简单吗?如果是,那么请你一定看看这篇文章!

    Cache Aside 读写策略也叫缓存旁路读写策略,从上图可以看出,针对读写的策略分别是:

    • 读流程:

    1. 首先从缓存中读取,如果有结果则直接返回结束
    2. 如果缓存中没有,则读 DB 并将结果回种缓存,然后返回结束
  • 写流程:

    1. 首先将将结果写入 DB
    2. 然后删除缓存中对应的值

    实际生产环境中,此种策略的使用也相对比较广泛,可以作为一种参考。这里需要注意一点的是,针对写流程,不能先删除缓存,在更新 DB,因为缓存删除后,此时 DB 还没有更新完时,来了一个 get 请求,那么缓存就有可能会被种入一个已失效的结果。

    Cache Aside 读写策略优缺点对比

    • 优点:

    1. 从流程图看,此种策略实现比较简单。
    2. 对于缓存和 DB 的一致性有了一定的保证,其可以解决第一种缓存方案遇到的问题。
  • 缺点:

    1. 很显然,每次更新数据,都会先更新 DB 紧接着就删除缓存,如果读写操作都比较频繁的情况下,势必使得缓存的命中率有所折扣,也就意味着缓存的 miss 率升高,从而导致在一定程度上削弱了缓存的作用。

    针对此种方案的缺点,其实也有一些比较折中的方案可以考虑。比如在更新 DB 完成后,同样更新缓存,但是在更新缓存的时候增加分布式锁避免;在比如如果业务场景并不是要求强一致性的话,可以将数据写入缓存并增加一个过期时间,这样即使数据不一致也只是一段时间。

    对于增加过期时间的这种方式,存在极热 key 的场景并不是适用的,因为一旦 key 过期后,在一瞬间大量请求越过缓存,直冲 DB,也就造成了缓存穿透的问题,所以 Cache Aside 方案看起来很不错,但是也不是万能的。

    Write/Read Through 策略

    Redis系列(七):缓存只是读写回种这么简单吗?如果是,那么请你一定看看这篇文章!

    Write/Read Through 的缓存策略不同于前两种,该策略需要引入第三方缓存同步插件。其读写流程如下:

    • 读流程:

    1. 首先读缓存,如果缓存命中,则直接返回结果
    2. 如果缓存未命中,则依赖第三方组件从 DB 中加载数据到缓存中,然后将获取的结果返回。
  • 写流程:

    1. 要更新的数据是否在缓存中存在,若存在则直接将数据写入缓存,之后缓存数据由第三方缓存组件将其更新到 DB
    2. 若缓存中不存在,则直接将结果写入 DB,这种称之为写穿透

    Write/Read Through 策略优缺点对比

    • 优点:

    1. 写缓存 miss 的情况除外,剩余所有操作都只与缓存进行交互,很大程度上避免了缓存与 DB 一直性的情况
  • 缺点:

    1. 从上面流程中不难看出,写缓存 miss 时直接与 DB 交互,会造成请求耗时增加
    2. 此种缓存策略引入了第三方缓存组件进行辅助,从而增加了系统的复杂度和系统的维护难度
    3. 由于需要引入第三方组件,而目前很多缓存如 Redis 原生并不兼容第三方组件,所以很难引入

    总和上面这些情况对比,目前采用此种缓存读写策略的场景很少,作者到目前还没有见过使用这种缓存策略的场景。

    Write Back 策略

    Write Back 策略是一种操作系统在使用的缓存读写策略,由于其实现比较复杂,所以读者朋友可以做一些了解即可,目前没有在生产环境中实际使用过。

    Redis系列(七):缓存只是读写回种这么简单吗?如果是,那么请你一定看看这篇文章!
    • 写操作流程如下:

    1. 写请求来之后,首先判断要写的 key 在缓存中是否被标记为“脏数据”,如果不是“脏数据”则直接写缓存,然后将其标记为脏数据
    2. 如果缓存中标记的是“脏数据”,则直接将其写入 DB,然后回种缓存,然后将其标记为“脏数据”
  • 读操作流程如下:

    1. 首先从缓存中获取数据,若有则直接返回
    2. 若缓存中没有,则寻找可用的缓存快,若缓存快被标记为“脏数据”,则将“脏数据”写入 DB,然后将缓存的数据标记为“非脏数据”,然后返回
    3. 若缓存快中的数据不是“脏数据”,则从 DB 中加载数据到缓存中,然后将其返回。

    生产环境中其他的缓存读写策略

    除了上面我们介绍的 4 中缓存读写策略,实际生产环境中还有一些比较常见的策略,比如针对热点 key 使用的 LRU 缓存策略。

    实际生产中,某些场景数据量是非常巨大的,比如微博用户 uid,方便查看某个用户的最近状态,如果全部将其全部都写入到缓存,显然是不合理的;一是缓存存储不了那么多用户信息,二是对应绝大部分用户是完全没有必要写入缓存的,因为对于很大一部分用户信息,只有很少的访问量。所以对于这种场景,只需要缓存最近经常被访问的那部分用户信息即可,针对这种场景,也就诞生了 LRU 缓存。

    其实 LRU 缓存在很多框架中也被广泛使用,需要的朋友可以自己研究下很简单的(这里其实也有有一道算法题,感兴趣的朋友可以自行在 LeetCode 上搜索)

    总结

    本文介绍了 5 中生产环境中经常用到的缓存读写策略,读者朋友们可以根据自己的实际业务场景,对其进行适当的改造就可以应用到自己的环境中了。好了,就讲这么多,更多的需要朋友们自行多多体会和应用。

    特别推荐一个分享架构+算法的优质内容,还没关注的小伙伴,可以长按关注一下:

    Redis系列(七):缓存只是读写回种这么简单吗?如果是,那么请你一定看看这篇文章!

    Redis系列(七):缓存只是读写回种这么简单吗?如果是,那么请你一定看看这篇文章!

    Redis系列(七):缓存只是读写回种这么简单吗?如果是,那么请你一定看看这篇文章!

    长按订阅更多精彩▼

    Redis系列(七):缓存只是读写回种这么简单吗?如果是,那么请你一定看看这篇文章!

    如有收获,点个在看,诚挚感谢

    免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
    换一批
    延伸阅读

    LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

    关键字: 驱动电源

    在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

    关键字: 工业电机 驱动电源

    LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

    关键字: 驱动电源 照明系统 散热

    根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

    关键字: LED 设计 驱动电源

    电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

    关键字: 电动汽车 新能源 驱动电源

    在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

    关键字: 发光二极管 驱动电源 LED

    LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

    关键字: LED 驱动电源 功率因数校正

    在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

    关键字: LED照明技术 电磁干扰 驱动电源

    开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

    关键字: LED 驱动电源 开关电源

    LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

    关键字: LED 隧道灯 驱动电源
    关闭