您好,欢迎来到12图资源库!分享精神,快乐你我!我们只是素材的搬运工!!
  • 首 页
  • 当前位置:首页 > 开发 > WEB开发 >
    Redis挂了,流量把数据库也打挂了,怎样办?
    时间:2021-08-10 21:14 来源:网络整理 作者:网络 浏览:收藏 挑错 推荐 打印

    Redis挂了,流量把数据库也打挂了,怎样办?

    你好呀,我是歪歪。

    是这样的,前几天有个读者给我发音讯,说面试的时分遇到一个场景题:

    Redis挂了,流量把数据库也打挂了,怎样办?

    他说他事先,一时间居然找不到回答成绩的角度,觉得本人没有回答到点子上。

    我细心想了一下,确实是感到这个成绩有一丝丝的奇异,有一种让人千言万语,又突然懵逼不知从何说起的神奇力气。

    为什么这么说呢?

    我们先读题啊,细心的读一遍题,我给你翻译一下。

    假设线上 Redis 挂了。然后一切央求打到数据库招致数据库也挂了。

    这是啥?

    Redis 挂了,不就是缓存都没了吗?

    缓存都没了,不就是缓存雪崩了吗?

    缓存雪崩了,不就招致数据库挂了吗?

    一提到“缓存雪崩”这四个字,缓存穿透、缓存击穿这几兄弟,是不是就立马条件反射的出如今你的脑海外面了,还顺带着对应的几套处置方案。

    然后就像背书似的,什么缓存全没了,什么缓存没有数据库中有,什么缓存和数据库中都没有...

    Redis挂了,流量把数据库也打挂了,怎样办?

    张口就是几分钟不带停顿的。

    另外关于缓存击穿缓和存穿透,很多同窗都会搞混。

    你换一个记法,缓存拆穿、缓存戳透。

    穿,只是穿过了缓存。

    透,是直接干究竟。

    你细品,应该就不会记混。

    Redis挂了,流量把数据库也打挂了,怎样办?

    除了下面的“Redis 缓存三连击”这一套八股文之外,还隐藏着另外一个八股文:

    Redis 挂了,为什么挂了?怎样就挂了?是不是有单点成绩?

    这不就是问你 Redis 效劳的高可用吗?

    说到 Redis 的高可用,脑子外面必须马上蹦出来主从、哨兵和集群吧?

    想到这些了,张口又是几分钟不带停顿的。

    但是这几分钟的千言万语,马上就被下面这个成绩给干懵逼了?

    这时该怎样停止恢复?

    如今问你怎样恢复,就是事中的事儿了。

    你得先说怎样恢复,再说怎样预防。

    你要是下去就回答前面说的什么“缓存三连击”、“高可用架构”,还包括大少数同窗能想到的多级缓存、限流措施、效劳升级、熔断机制,这些都有点牵强。

    由于毕竟这些手腕都是事前的预防措施,下去就说这些背书痕迹比较清楚。

    答一定是要答的,从事中恢复过度到事前预防方案,而且重点就是事前预防,那么我们怎样过度的自然一点呢?

    先说事中怎样恢复,其实我觉得几句话就说完了。

    效劳挂了啊,老哥,还能怎样恢复,当然是重启效劳啊。

    站在运维人员的角度,当然优先思索是先把 Redis 和数据库效劳重新启动起来啦。

    但是启动之前得先做个小操作,把流量摘掉,可以先把流量阻拦在入口的中央,比如复杂粗犷的经过 Nginx 的配置把央求都转到一个精心设计的错误页面,就是说这么一个意思。

    这样做的目的是为了避免流量过大,直接把新启动的效劳,启动一个打挂一个的状况出现。

    要是启动起来又扛不住了,请在心里默念散布式系统三大利器:

    Redis挂了,流量把数据库也打挂了,怎样办?

    不行就加钱,堆机器嘛。

    要觉得堆机器没啥技术含量,你就再从缓存预热的角度答一个。

    就是当 Redis 效劳重新启动后,经进顺序先放点已知的热点 key 出来后,系统再对外提供效劳,避免缓存击穿的场景。

    而且下面这一系列操作其实和开发人员的关系不大,主要是运维同窗干的事儿。

    开发同窗最多就是在设计效劳的时分做到效劳有形状,以到达快速水平扩容的目的。

    至于怎样去快速水平扩容,那是运维同窗的事儿,暂时不要去抢别人的饭碗。

    答到这,你就可以用“但是”来过度到事前预防,末尾本人的表演了。

    故作沉思的对面试官说“but”了:

    Redis挂了,流量把数据库也打挂了,怎样办?

    我觉得从技术方案的角度来说,我们应该做到事前预防。

    这一切的成绩都是由于 Redis 崩了,也就是发作了缓存雪崩。

    在高并发的状况下,除了缓存雪崩,我们还必须得思索到缓存的击穿、穿透成绩。

    而且 Redis 为什么会崩了?是不是运用姿态不对?是不是没有保证高可用?

    效劳中是不是需求思索限流或许熔断机制,最大水平的保护顺序的运转?

    或许我们能否应该树立多级缓存的机制,避免 Redis 挂掉之后,大批流量直接打到 MySQL 效劳招致数据库的崩盘?

    至此,“but”完成,答题的方向从事中恢复,转向了事前预防,进入了我们的强项,八股文专场,然后就可以末尾“背诵”了。

    我这里复杂的聊一下缓存成绩三连击和 Redis 的高可用。

    至于多级缓存,可以看看我之前发的这篇文章:《这波舒适了,落地多级缓存!》。

    缓存击穿

    先说一下缓存击穿的概念。

    缓存击穿是指一个央求要拜访的数据,缓存中没有,但数据库中有的状况。

    Redis挂了,流量把数据库也打挂了,怎样办?

    这种状况普通来说就是缓存过时了。

    但是这时由于并发拜访这个缓存的用户特别多,这是一个热点 key,这么多用户的央求同时过去,在缓存外面没有取到数据,所以又同时去拜访数据库取数据,惹起数据库流量激增,压力瞬间增大,直接崩溃给你看。

    所以一个数据有缓存,每次央求都从缓存中快速的前往了数据,但是某个时间点缓存失效了,某个央求在缓存中没有央求到数据,这时分我们就说这个央求就"击穿"了缓存。

    针对这个场景,对应的处置方案普通来说有三种。

    第一个就是只放行一个央求到数据库,然后做构建缓存的操作。

    多个央求只放行一个,怎样做?

    就借助 Redis setNX 命令设置一个标志位就行。设置成功的放行,设置失败的就轮询等候。

    第二个处置方案就是后台续命。

    这个方案的思想就是,后台开一个定时义务,专门自动更新行将过时的数据。

    比如顺序中设置 why 这个热点 key 的时分,同时设置了过时时间为 10 分钟,那后台顺序在第 8 分钟的时分,会去数据库查询数据并重新放到缓存中,同时再次设置缓存为 10 分钟。

    怎样样,是不是有点 Redisson 散布式锁看门狗的滋味?

    我觉得思想是一脉相承的。

    只是方案落地的时分,从代码编写的角度来说稍微费事了一点。

    我曾经也借助这个思想开发过一个流水号系统。

    大约是这样的。

    流水号系统,属于十分关键的系统,为了降低数据库异常对效劳带来的冲击,所以效劳启动后会就会为每种业务系统都预先在缓存中缓存 5000 个流水号。

    然后后台 Job 定时反省缓存中还剩下多少流水号,假设小于 1000 个,则再预先生成新的流水号,补充到缓存中,让缓存中的流水号再次回到 5000 个。

    这样做的益处就是数据库异常后,我至少保证还有 5000 个缓存可以保证下游业务,我有一定的时间去恢双数据库。

    这也算是一种后台续命的思想。

    第三个办法就复杂了:永不过时。

    缓存为什么会被击穿,是不是由于设置了超时时间,然后被回收了?

    那我不设置超时时间不就行了?

    假设结合实践场景你用脚趾头都能想到这个 key 一定会是个热点 key,会有少量的央求来拜访这个数据。而且这个 key 对应的 value 不会发作变化。

    关于这样的数据你还设置过时时间干什么?

    直接放出来,永不过时。

    其实下面的后台续命思想的最终表现是也是永不过时。

    只是后台续命的思想,会自动更新缓存,适用于缓存会变的场景。会出现缓存不分歧的状况,取决于你的业务场景能接受多长时间的缓存不分歧。

    总之,详细状况,详细剖析。

    但是思绪要明晰,最终方案都是常规方案的组合或许变种。

    缓存穿透

    那么啥又是缓存穿透呢?

    缓存穿透是指一个央求要拜访的数据,缓存和数据库中都没有,而用户短时间、高密度的发起这样的央求,每次都打到数据库效劳上,给数据库形成了压力。

    Redis挂了,流量把数据库也打挂了,怎样办?

    普通来说这样的央求属于恶意央求。

    就比如说,我这是一个技术群众号,你明明知道我没有,但是你非要来我这里买一瓶啤酒,恶意央求。

    怎样处置呢?

    两个方案。

    第一个缓存空对象。

    就是在数据库即使没有查询到数据,我们也把这次央求当做 key 缓存起来,value 可以是 NULL。

    下次异样央求就会命中这个 NULL,缓存层就处置了这个央求,不会对数据库产生压力。

    这样完成起来复杂,开发成本很低。

    但这样随之而来的一个面试题必需要留意一下:

    关于恶意攻击,央求的时分key往往各不相反,且只央求一次,那你要把这些 key 都缓存起来的话,由于每个 key 都只央求一次,那还是每次都会央求数据库,没有保护到数据库呀?

    这个成绩,布隆过滤器,了解一下?

    关于布隆过滤器我之前写过这篇文章,可以看看:《布隆,牛逼!布谷鸟,牛逼!》

    布隆过滤器的特性是说某个值存在时,这个值能够不存在。当它说不存在时,那就一定不存在。

    所以可以基于这个特性,把已有数据都构建到布隆过滤器外面去。

    然后它可以帮忙挡住绝大部分的攻击。

    但是还有个比较容易无视的连环炮成绩:

    面试官:布隆过滤器容量有限且不支持删除,随着外面内容的添加,误判率就会随之上升。请问,这个成绩你们是怎样处置的?

    也是两个答题方向。

    首先,不支持删除的话,就换一个支持删除的布隆过滤器的轮子咯。

    比如我前面的文章中提到的布谷鸟过滤器。

    或许就是提早重构布隆过滤器。

    比如在容量到达 50% 的时分,就央求一个新的更大的布隆过滤器来交流掉之前的过滤器。

    只是需求留意的是,重建你得知道有那些数据需求停止重建的,所以你得有个中央来记载。

    比如就是 Redis、数据库,甚至内存缓存都可以。

    衰败地过没关系,你底气十足的回答就行了。

    你要置信,面试官八成也衰败地过,你们看的说不定都是同一份材料呢。

    缓存雪崩

    缓存雪崩是指缓存中大少数的数据在同一时间抵达过时时间,而查询数据量庞大,这时分,又是缓存中没有,数据库中有的状况了。

    Redis挂了,流量把数据库也打挂了,怎样办?

    央求都打到数据库上,惹起数据库流量激增,压力瞬间增大,直接崩溃给你看。

    和前面讲的缓存击穿不同的是,缓存击穿指少量的央求并发查询同一条数据。

    缓存雪崩是不同数据都到了过时时间,招致这些数据在缓存中都查询不到,

    雪崩,还是用的很笼统的。

    避免雪崩的方案复杂来说就是错峰过时。

    在设置 key 过时时间的时分,在加上一个短的随机过时时间,这样就能避免少量缓存在同一时间过时,惹起的缓存雪崩。

    假设发了雪崩,我们可以有效劳升级、熔断、限流手腕来拒绝一些央求,保证效劳的正常。

    但是,这些对用户体验是有一定影响的。假定我们的顺序有这的逻辑,也是拿来兜底的,从用户的角度来说,是不希望走到这样的逻辑中去。

    所以,还是以预防雪崩为主。

    最后还有一种雪崩,就是整个 Redis 效劳都挂了。

    所以,接上去就要聊聊 Redis 效劳的高可用架构了。

    Redis 高可用架构

    聊到 Redis 高可用架构,大家基本上都能想到主从、哨兵、集群这三种形式。

    主从结构很复杂,就不说了,其弊端主要是出现缺点的时分需求人工介入干预,需求人工介入的,就不是真正的高可用。

    哨兵和集群这两种是写在官网上的方案:

    https://redis.io/topics/introduction

    (责任编辑:admin)