缓存一定要用redis吗

缓存一定要用redis吗

「缓存」,写程序的肯定都用过。

使用缓存的目的只有2个:提升速度、减轻数据库压力。

使用缓存虽然也很简单的,但还是有很多细节可以推敲。

经典的缓存更新策略

我就先摆一些经典的缓存模式,其实我们有时候都不知道它是一个模式的时候,都已经在用了。

一般有以下几种:

  • Cache Aside
  • Read/Write Through
  • Write Behind

名字看上去很专业,但其实原理都比较简单,大家有时间可以去网上搜一下,我很多也是搜回来的,下面我只挑里面重点讲扼要。

Cache Aside

Cache-Aside-Design-Pattern-Flow-Diagram-e1470471723210.png
Updating-Data-using-the-Cache-Aside-Pattern-Flow-Diagram-1-e1470471761402.png

上面就是整个更新缓存的流程图,重点我们可以看下面的图更新缓存的方式:

  • 先更新数据库
  • 再把缓存的数据失效

缓存失效了后,等下次Application再请求数据的时候,就会回到第一张图,如此循环。

其实这个就是我们经常使用的更新缓存逻辑,但这里存在一个高并发情况下的问题。

  • 缓存初始化为空,A请求数据,就去数据库查询到了数据,并准备放到缓存。即执行了上图的1、2,3还没执行。
  • 此时B请求并发,更新数据库,并使缓存为空。也就是下图的1、2。
  • 最后A请求执行步骤3,设置缓存并返回结果。这时候其实缓存里面的数据是「脏数据」,因为B的更新并没有读到缓存里。

然而高并发情况触发条件比较苛刻,所以如果对缓存再加上一个适当的TTL(Time To Live,过期时间),缓存数据的准确性要求不高,那问题就不大。

Read/Write Through

Read/Write Through 更新逻辑如下所示

dcc0b5c52ce691ac9fbd591f0d5a4a82_1440w.jpg

咋看其实跟上面Cache Aside没什么区别,但架构上多了一个Cache的服务,Cache服务层充当写入、更新、读取缓存的服务。

整体数据流就是:应用 > Cache 服务 > 数据库。所以跟Cache Aside最大的区别在于:

  • Cache Aside是直接应用跟数据库打交道,缓存的更新逻辑有应用自己完成。
  • Read/Write Through 在应用和数据库之间多了一个“Cache 服务”,从而应用和数据库解耦。
  • 解耦的好处在于,应用再也不需要关注缓存的更新逻辑,每次读取、更新数据都是跟Cache 服务交互;Cache 服务专注于缓存的更新以及数据库的同步即可。

Write Behind

Write Behind 更新逻辑如下所示

293f4fd60aa7cc24c7b233d2f543ba21_1440w.jpg

截取《缓存更新的套路》的一段话解释

Write Back套路,一句说就是,在更新数据的时候,只更新缓存,不更新数据库,而我们的缓存会异步地批量更新数据库。这个设计的好处就是让数据的I/O操作飞快无比(因为直接操作内存嘛 ),因为异步,write back还可以合并对同一个数据的多次操作,所以性能的提高是相当可观的。

但是,其带来的问题是,数据不是强一致性的,而且可能会丢失,但软件设计没有完美,都是权衡取舍。

另外,Write Back实现逻辑比较复杂,因为他需要track有哪数据是被更新了的,需要刷到持久层上。操作系统的write back会在仅当这个cache需要失效的时候,才会被真正持久起来,比如,内存不够了,或是进程退出了等情况,这又叫lazy write。

如果中间件服务挂掉呢

其实可以看出,上面几个缓存使用策略,逻辑都是 Cache Aside 基础上强化改造。那我们回到 Cache Aside 的逻辑看,除了上面说的 “高并发” 问题,其实还有其他问题。

回忆一下,在Cache Aside的模式中,我们在更新缓存:

  • 是先更新完数据库。
  • 再直接把缓存失效;
  • 待下次读取缓存数据的时候,再从数据库加载新数据;
  • 加载到缓存中,再返回数据。
image-20210125194734959.png

一般来说,程序部署标准都是用各种中间件,比如一个程序用了缓存,就用redis;数据库,就用mysql。那么一个完整的程序,就有程序应用实例、redis、数据库,当三个服务都正常时,就会提供正常响应,但如果redis或者数据库访问异常呢。

redis 异常

如果redis异常的话,一般程序会有2种表现:

  • 程序没cache到redis异常,或者没有做处理,程序不返回数据直接报错。redis 属于数据缓存,缓存崩溃导致整体程序不可用,对于某些高可用场景来说未必是可以接受的;没了缓存性能、效率、吞吐量会降低,可以限流提供有限服务,但不能完全不提供。
  • 程序cache到redis异常,并且跳过了redis,每一次的抓取数据都要访问DB,这个比上面的表现要好,因为起码对外仍然提供了服务;但如果没有有效的限流,高并发下就会造成「缓存击穿」,大量查询可能直接把数据库搞挂。

数据库异常

数据库异常本身就是比较大的故障,整体程序应该大部分都不能用。

但有时偶尔的网络抖动导致访问失败也是有可能的,那如果刚好缓存被设置为失效,又请求数据库失败的这种情况下,就会返回失败。

这种情况下,如果redis缓存还有旧数据,就可以暂时返回给用户。

真的要用中间件吗

理论上来说,redis和数据库作为中间件而言,一般都是具有较高可用性,比如腾讯云上的redis就达到99.5%。

image-20210210091338201.png

但中间件终归是一种共享服务,除了本身的稳定性,还需要依赖网络的稳定性,相互请求也需要带宽。

回到「缓存」这个主题上来,要增加使用缓存的稳定性,还有一个可以考虑的点,就是是否真的需要使用redis。因为少一个外部依赖点,程序性能相对稳定性可控。

假如程序里面的缓存符合以下特性:

  • 缓存数据不需要锁,多个实例不需要共享、统计。
  • 缓存数据的量是可以统计到并预计到内存的使用量,要避免本地内存使用影响程序本身的服务。
  • 缓存不需要考虑持久化,进程重启后可以随时重新获取。

符合以上特性,其实建议还是使用本地缓存,缺点就是增加了代码复杂度,要考虑过期、线程安全等;但对应也是有措施,可以用一些框架来缓解代码复杂度的问题。

本地缓存另外一个问题就是缓存更新,因为在分布式系统下,同一个应用的缓存就散落到各个实例上,如何主动统一刷新多态进程实例的缓存也是一个问题。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容

  • Redis由于将数据保存在内存中,访问速度远远大于基于磁盘的数据库(如MySQL)。但是由于其容量有限,不开启持久...
    925781609阅读 837评论 0 3
  • 1. 缓存的基本思想 很多朋友,只知道缓存可以提高系统性能以及减少请求相应时间,但是,不太清楚缓存的本质思想是什么...
    前端三少爷阅读 178评论 0 0
  • 缓存架构 脑中的直观反应 SQLAlchemy起到一定的本地缓存作用在同一请求中多次相同的查询只查询数据库一次,S...
    大金叶子阅读 2,920评论 0 2
  • 概述 本节学习下“缓存 + 数据库”模型读写的一致性问题,比如,缓存中是否有可能被写入脏数据,策略的读写性能如何,...
    进击的蚂蚁zzzliu阅读 773评论 0 1
  • 推荐指数: 6.0 书籍主旨关键词:特权、焦点、注意力、语言联想、情景联想 观点: 1.统计学现在叫数据分析,社会...
    Jenaral阅读 5,700评论 0 5