一提到Redis缓存,我们不得不了解的三个问题就是:缓存雪崩、缓存击穿和缓存穿透。这三个问题一旦发生,会导致大量的请求直接请求到数据库层。如果并发压力大,就会导致数据库崩溃。那p0级的故障是没跑了。

今天我们就来详细的了解这个三个问题诱因以及如何解决。

废话不多说,我们直接开搞!!!

一、缓存雪崩

什么是缓存雪崩?缓存雪崩就是大量请求无法在redis缓存中进行处理,而是直接发送到了数据库层,使得数据库压力陡增。就好像redis一下子突然失效了一样。一般造成缓存雪崩主要有两个原因,我们来一一分析一下。

1.缓存中大量数据同时过期

缓存中大量数据同时过期,就会导致大量请求无法在redis缓存层面进行处理。具体来说,就是给redis中大量数据设置了相同的过期时间,一旦它们同时失效,应用就会把请求直接发送给数据库,直接从数据库中读取数据。如果应用的并发量很大,那数据库的压力就会很大。如下图所示: 

针对大量数据同时失效带来的缓存雪崩问题,我们一般采取以下两种解决方案。   (1)我们在开发过程中要避免给大量数据设置相同的过期时间。我们可以在给数据设置过期时间时给时间加一个很小的随机数,这样不同数据的过期时间就会有所差别,但差别也不会太大,保证数据在一定范围内过期,从而满足业务层要求同时过期的需要。   (2)服务降级。所谓的服务降级,是指发生缓存雪崩后,针对不同的数据采取不同的策略。

  • 当业务访问非核心数据时(例如商品属性信息),我们直接返回预定义的信息。
  • 当业务访问的是如库存数据等核心数据时,仍然允许查询缓存,如果缓存缺失,也可以从数据库中继续读取。

这样一来,只有部分过期的数据会访问数据库,所以数据库压力就没那么大。

2.Redis实例发生故障

当Redis实例发生故障,那就相当于缓存已经废掉了,所以大量请求会直接请求数据库,造成数据库压力变大,甚至宕机。针对这种情况发生的缓存雪崩,我们有以下两种处理方式。 (1)在业务系统侧实现服务熔断或请求限流机制    所谓的服务熔断,就是指在发生缓存雪崩时,为了防止大流量直接打到数据库,我们会暂停对缓存系统的访问。当上层应用访问缓存时,缓存接口不会去访问Redis实例,而是直接返回。等redis恢复后,再允许应用程序请求缓存系统。这样就会避免因为redis缓存宕机,导致数据库压力陡增的情况。
   服务熔断虽然可以保证数据库不被崩溃,但是暂停了整个服务的访问,对业务的影响范围大,为了减小对上层服务的影响,我们一般采用请求限流。请求限流是指业务系统去控制每秒进入系统的请求数,避免过多的请求被发送到数据库。比如正常运行时,业务系统每秒进入的请求是1万个,其中有80%在缓存中就可以处理了,有20%会去数据库中处理。一旦发生缓存雪崩,100%的流量就会请求数据库,为了不造成数据库崩溃,我们就可以启动请求限流机制。业务系统只允许30%的流量进入,而70%的流量被拒绝服务。这也是目前主流大厂常用的方法,比如在某个明星爆出大瓜后,我们刷微博经常刷不出来,多刷几次就能进入,那就是因为做了服务降级。只允许一部分流量进入。 

   (2)使用高可靠集群

我们可以通过主从节点来部署高可靠的Redis集群。当主节点挂掉后,从节点还可以切换成主节点。

二、缓存击穿

缓存击穿是指针对某个热点数据,无法在缓存中进行处理,然后访问该数据的大量请求,一下子都发到后端数据库中,导致数据库压力激增。对于缓存击穿的情况,经常发生在热点数据过期失效时
    为了避免这种情况发生,最常采取的措施就是对于访问特别频繁的热点数据,我们就不设置过期时间了。这样一来,对热点数据的访问,都可以在缓存中进行。

三、缓存穿透

缓存穿透是指要访问的数据既不在缓存中,也不在数据库中,会导致请求缓存时,发生缓存缺失,然后请求数据库,发现数据库中也没有需要的数据。这样一来,缓存就成了“摆设”,如果有大量的这种请求,就会给数据库带来很大的压力。
   这个问题一般都是黑客进行恶意攻击造成的。为了避免这种问题发生,我们有三种解决方式。

1、缓存空值或者缺省值

一旦发生缓存穿透,我们就可以在redis中设置一个空值或者给定的某个缺省值。这样,业务应用的后续这种请求,都可以命中缓存。这样就避免了把大量请求发送给数据库了。

2、使用布隆过滤器来快速判断数据是否存在

这里我们先来解释一下什么是布隆过滤器。
   布隆过滤器由一个初值都为0的bit数组和N个哈希函数组成,可以用来快速判断某个数据是否存在。当我们想标记某个数据存在时,布隆过滤器会通过三个操作来完成标记:

  • 首先,使用N个哈希函数,分别计算数据的哈希值,得到N个哈希值。
  • 然后把这N个哈希值对bit数组的长度取模,得到每个哈希值在数组中的位置。
  • 最后,我们把对应位置的bit位设置为1,这样就完成了布隆过滤器中标记数据的操作。

如果数据不存在,也就是我们没有用布隆过滤器标记过,bit数组对应的bit位为0。    当我们需要判断某个数据是否存在时,我们就执行上面的计算过程,我们先求出这个数据对应的hash值,然后取模,然后去bit数组查这N个位置上的bit值。只要这N个bit值有一个不为1,就表明这个数据没有被标记过。    基于布隆过滤器的快速检测特性,我们可以把数据写入数据库时,使用布隆过滤器做个标记,当缓存失效后,上层应用查询数据库时,可以通过查询布隆过滤器快速判断数据是否存在。如果不存在,就不用在去数据库中去查了。这样一来,即使发生缓存穿透,也不会对数据库造成压力。

3、业务层对请求进行检测

缓存穿透发生的原因主要就是恶意请求访问不存在的数据,所以业务层接受到请求后,一定要进行合法性检测,把恶意请求给过滤掉,这样就可以避免缓存穿透的问题了。

今天我们就聊到这里,如果感兴趣,记得关注一波公众号【程序员学长】,有你意想不到的收获哦。

阿里面试Redis常考问题的更多相关文章

  1. 害...原来阿里面试Redis最常问的是它呀

    一提到Redis缓存,我们不得不了解的三个问题就是:缓存雪崩.缓存击穿和缓存穿透.这三个问题一旦发生,会导致大量的请求直接请求到数据库层.如果并发压力大,就会导致数据库崩溃.那p0级的故障是没跑了. ...

  2. http面试笔试常考知识点(二)

    接上一篇随笔 1. https协议为什么比http安全? 内容加密:建立一个信息安全通道,确保信息传输安全: 身份认证:确保网站的真实性: 数据完整性校验:防止内容被第三方冒充或者篡改 2.常见状态码 ...

  3. Java面试2018常考题目汇总

    一.JAVA基础篇-概念 1.简述你所知道的Linux: Linux起源于1991年,1995年流行起来的免费操作系统,目前, Linux是主流的服务器操作系统, 广泛应用于互联网.云计算.智能手机( ...

  4. http面试笔试常考知识点(一)

    1.什么是http HTTP是客户端和服务器端请求和应答的标准.通过使用Web浏览器.网络爬虫或者其它的工具,客户端发起一个到服务器上指定端口(默认端口为80)的HTTP请求.(我们称这个客户端)叫用 ...

  5. 面试中常考的字符串操作方法大全,包含ES6

    原文链接:http://caibaojian.com/js-string.html 一.charAt() 返回在指定位置的字符. var str="abc" console.log ...

  6. PHP面试常考内容之Memcache和Redis(2)

    你好,是我琉忆.继周一(2019.2-18)发布的"PHP面试常考内容之Memcache和Redis(1)"后,这是第二篇,感谢你的支持和阅读.本周(2019.2-18至2-22) ...

  7. PHP面试常考内容之Memcache和Redis(1)

    你好,是我琉忆.继上周(2019.2-11至2-15)发布的"PHP面试常考内容之面向对象"专题后,发布的第二个专题,感谢你的阅读.本周(2019.2-18至2-22)的文章内容点 ...

  8. Java面试题中常考的容易混淆的知识点区别

    以下是我收集的Java编程里各种区别,供Java学习爱好者参考,这些区别都是每次Java面试中常考的,大家好好掌握,如有失误请留言指出.想要获取Java详细全套学习资料请到上海尚学堂官网获取. 1.H ...

  9. C/C++求职宝典21个重点笔记(常考笔试面试点)

    这是我之前准备找工作时看<C/C++求职宝典>一书做的笔记,都是一些笔试面试中常考的重点难点问题,但比较基础,适合初学者看. 1. char c = '\72'; 中的\72代表一个字符, ...

随机推荐

  1. 「一本通 3.1 练习 4」Tree 题解

    题目描述 原题来自:2012 年国家集训队互测 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有 条白色边的生成树.题目保证有解. 输入格式 第一行V,E,need 分别表示点数, ...

  2. Docker:虚拟机挂起后,再启动docker容器连接失败

    问题描述 当我们使用VMware15 Pro 创建虚拟机并运行Linux搭建的Docker时,挂起虚拟机后再次运行发现访问Docker容器失败. 解决方式  我们正常的挂起其实是:挂起客户机,博主尝试 ...

  3. Hibernate框架(一)总结介绍

    作为SSH三大框架之一的Hibernate,是用来把程序的Dao层和数据库打交道用的,它封装了JDBC的步骤,是我们对数据库的操作更加简单,更加快捷.利用Hibernate框架我们就可以不再编写重复的 ...

  4. elf文件结构解读以及plt节got节的理解

    前言: 熟悉elf文件结构是一件很不错的事,因为安卓中的so加固以及修复都是需要这些知识的,包括pwn里面的rop之类的,也都是 和got节,plt节息息相关的,个人建议是在搞懂elf文件结构后,自己 ...

  5. XCTF(MISC) 坚持60s

    题目描述:菜狗发现最近菜猫不爱理他,反而迷上了菜鸡 下载附件,发现是一个游戏,同时要玩到60s才能得到flag(可恶,完全玩不到60s,被疯狂嘲讽) ------------------------- ...

  6. buu pyre

    一.下载附件是是pyc的字节码文件,找个在线网站反编译一下 思路还是挺清晰: 先逆着求出code, 这里就是求余,有点麻烦,那个+128%128其实没啥用的,省略就好了 算法里面再处理一下细节,跑一下 ...

  7. [源码解析] 深度学习分布式训练框架 horovod (15) --- 广播 & 通知

    [源码解析] 深度学习分布式训练框架 horovod (15) --- 广播 & 通知 目录 [源码解析] 深度学习分布式训练框架 horovod (15) --- 广播 & 通知 0 ...

  8. Vue高阶

    Vue.cli是基于vue应用开发提供的一个脚手架工具,为应用搭建基础的框架架构,提供插件.开发服务.打包等功能. 1. 安装 node.js是一个JavaScript的运行环境,提供了一个事件驱动. ...

  9. Docker实现退出container后保持继续运行的解决办法

    现象: 运行一个image,例如ubuntu14.04: 1 docker run -it --rm ubuntu:14.04 bash 退出时: 执行Ctrl+D或者执行exit 查看线程: 1 d ...

  10. File类与常用IO流第十章——序列化流

    第十章.序列化流 序列化流和反序列化流概述 序列化:用一个字节序列表示一个对象,该字节序列包含该对象的数据.对象的类型和对象中存储的属性等等信息.字节序列写出到文件后,相当于文件中持久保存了一个对象的 ...