Redis挂了,流量把数据库也打挂了,怎么办? (上)

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis挂了,流量把数据库也打挂了,怎么办? (上)

image.png

他说他当时,一时间竟然找不到回答问题的角度,感觉自己没有回答到点子上。

我仔细想了一下,确实是感到这个问题有一丝丝的奇怪,有一种让人千言万语,又突然懵逼不知从何说起的神奇力量。

为什么这么说呢?

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

如果线上 Redis 挂了。然后所有请求打到数据库导致数据库也挂了。

这是啥?

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

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

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

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

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

image.png

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

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

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

穿,只是穿过了缓存。

透,是直接干到底。

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

image.png

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

Redis 挂了,为什么挂了?怎么就挂了?是不是有单点问题?

这不就是问你 Redis 服务的高可用吗?

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

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

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

这时该怎么进行恢复?

现在问你怎么恢复,就是事中的事儿了。

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

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

因为毕竟这些手段都是事前的预防措施,上来就说这些背书痕迹比较明显。

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

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

服务挂了啊,老哥,还能怎么恢复,当然是重启服务啊。

站在运维人员的角度,当然优先考虑是先把 Redis 和数据库服务重新启动起来啦。

但是启动之前得先做个小操作,把流量摘掉,可以先把流量拦截在入口的地方,比如简单粗暴的通过 Nginx 的配置把请求都转到一个精心设计的错误页面,就是说这么一个意思。

这样做的目的是为了防止流量过大,直接把新启动的服务,启动一个打挂一个的情况出现。

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

image.png


不行就加钱,堆机器嘛。

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

就是当 Redis 服务重新启动后,通过程序先放点已知的热点 key 进去后,系统再对外提供服务,防止缓存击穿的场景。

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

开发同学最多就是在设计服务的时候做到服务无状态,以达到快速水平扩容的目的。

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

答到这,你就可以用“但是”来过度到事前预防,开始自己的表演了。

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


image.png


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

这一切的问题都是因为 Redis 崩了,也就是发生了缓存雪崩。

在高并发的情况下,除了缓存雪崩,我们还必须得考虑到缓存的击穿、穿透问题。

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

服务中是不是需要考虑限流或者熔断机制,最大程度的保护程序的运行?

或者我们是否应该建立多级缓存的机制,防止 Redis 挂掉之后,大批流量直接打到 MySQL 服务导致数据库的崩盘?

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

我这里简单的聊一下缓存问题三连击和 Redis 的高可用。

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


缓存击穿


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

缓存击穿是指一个请求要访问的数据,缓存中没有,但数据库中有的情况。

image.png

这种情况一般来说就是缓存过期了。

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

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

针对这个场景,对应的解决方案一般来说有三种。

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

多个请求只放行一个,怎么做?

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

  • 第二个解决方案就是后台续命。

这个方案的思想就是,后台开一个定时任务,专门主动更新即将过期的数据。

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

怎么样,是不是有点 Redisson 分布式锁看门狗的味道?

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

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

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

大概是这样的。

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

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

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

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

  • 第三个方法就简单了:永不过期。

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

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

如果结合实际场景你用脚趾头都能想到这个 key 一定会是个热点 key,会有大量的请求来访问这个数据。而且这个 key 对应的 value 不会发生变化。

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

直接放进去,永不过期。

其实上面的后台续命思想的最终体现是也是永不过期。

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

总之,具体情况,具体分析。

但是思路要清晰,最终方案都是常规方案的组合或者变种。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
1月前
|
存储 NoSQL Redis
【Redis】利用Redis List实现数据库分页快速查询
【Redis】利用Redis List实现数据库分页快速查询
111 0
|
1月前
|
存储 缓存 NoSQL
利用Redis List实现数据库分页快速查询的有效方法
利用Redis List实现数据库分页快速查询的有效方法
|
2月前
|
缓存 NoSQL 关系型数据库
亿级电商流量,高并发下Redis与MySQL的数据一致性如何保证
你们有多少人是被面试官问到过Redis和MySQL的数据一致性如何保证的? 你们是否考虑过在高并发场景下,Redis与MySQL的同步会有哪些问题?该如何解决? 本篇文章会带大家详细了解,让你知其然,知其所以然,吊打面试官。
363 0
亿级电商流量,高并发下Redis与MySQL的数据一致性如何保证
|
1月前
|
NoSQL Java 数据库连接
使用Java实现从数据库查出数据存入Redis,并在查询时先查Redis,如果Redis中没有数据再从数据库中读取
使用Java实现从数据库查出数据存入Redis,并在查询时先查Redis,如果Redis中没有数据再从数据库中读取
356 1
|
7天前
|
NoSQL MongoDB Redis
Python与NoSQL数据库(MongoDB、Redis等)面试问答
【4月更文挑战第16天】本文探讨了Python与NoSQL数据库(如MongoDB、Redis)在面试中的常见问题,包括连接与操作数据库、错误处理、高级特性和缓存策略。重点介绍了使用`pymongo`和`redis`库进行CRUD操作、异常捕获以及数据一致性管理。通过理解这些问题、易错点及避免策略,并结合代码示例,开发者能在面试中展现其技术实力和实践经验。
129 8
Python与NoSQL数据库(MongoDB、Redis等)面试问答
|
23天前
|
存储 缓存 NoSQL
Redis 服务器指南:高性能内存数据库的完整使用指南
Redis 服务器指南:高性能内存数据库的完整使用指南
|
1月前
|
缓存 NoSQL 数据库
[Redis]——数据一致性,先操作数据库,还是先更新缓存?
[Redis]——数据一致性,先操作数据库,还是先更新缓存?
|
16天前
|
NoSQL Linux Redis
06- 你们使用Redis是单点还是集群 ? 哪种集群 ?
**Redis配置:** 使用哨兵集群,结构为1主2从,加上3个哨兵节点,总计分布在3台Linux服务器上,提供高可用性。
230 0
|
25天前
|
负载均衡 监控 NoSQL
Redis的集群方案有哪些?
Redis集群包括主从复制(基础,手动故障恢复)、哨兵模式(自动高可用)和Redis Cluster(官方分布式解决方案,自动分片和容错)。此外,还有如Codis、Redisson和Twemproxy等第三方工具用于代理和负载均衡。选择方案需考虑应用场景、数据规模和并发需求。
199 2
|
30天前
|
NoSQL Redis
Redis集群(六):集群常用命令及说明
Redis集群(六):集群常用命令及说明
193 0

热门文章

最新文章