[Redis] Redis的三大缓存异常原因分析和解决方案
Redis的三大缓存异常原因分析和解决方案
缓存的三个异常分别是缓存击穿、缓存雪崩、缓存穿透。这三个问题一旦发生,会导致大量的请求积压到数据库层,并发量巨大的情况下很有可能导致数据库宕机或是故障,造成严重的生产事故。
接下来就来看看这三种缓存异常的原因分析和解决方案。
缓存击穿
缓存击穿是指针对某个热点数据的请求,无法在缓存中处理,导致大量的针对该数据的请求一下子全都发送到了后端数据库,使数据库压力激增,影响到数据库处理其他的请求。
产生原因
缓存击穿的情况,经常是发生在热点数据过期失效的情况。
如下图:
解决方案
对于缓存击穿,解决方案其实也很直接。对于访问很频繁的热点数据,就不需要设置过期时间了。这样对热点数据的访问可以直接在缓存中进行处理,Redis的数万级别的高吞吐量可以很好的应对大量的并发请求。
缓存雪崩
缓存雪崩指的是大量的应用请求无法在Redis缓存中进行处理,从而被发送到数据库层,导致数据库层的压力激增。
产生原因
产生原因一般有两种情况。
第一种情况:缓存中有大量的数据同时过期,导致请求无法得到处理。
具体来说,当数据保存在缓存中,并且设置了过期时间时,如果在某一个时刻,大量数据同时过期,此时,应用再访问这些数据的话,就会发生缓存缺失。紧接着,应用就会把请求发送给数据库,从数据库中读取数据。如果应用的并发请求量很大,那么数据库的压力也就很大,这会进一步影响到数据库的其他正常业务请求处理。
如下图:
第二中情况:Redis缓存实例发生故障,宕机了,导致大量请求积压到数据库。
一般来说,一个 Redis 实例可以支持数万级别的请求处理吞吐量,而单个数据库可能只能支持数千级别的请求处理吞吐量,它们两个的处理能力可能相差了近十倍。由于缓存雪崩,Redis 缓存失效,所以,数据库就可能要承受近十倍的请求压力,从而因为压力过大而崩溃。
解决方案
针对缓存中有大量的数据同时过期的情况,可以提供两种解决方案。
- 微调过期时间:给数据的到期时间增加一个较小的随机数,避免给大量的数据设置相同的过期的时间
- 服务降级:当发生缓存雪崩时,针对不同的数据采取不同的处理方式。
- 非核心数据:暂时停止从缓存中查询这些数据,而是直接返回预定义信息、空值或者是错误信息。
- 核心数据:缓存数据丢失时通过数据库读取。
使用服务降级的方式,只有部分的数据请求会被发送到数据库,则数据库的压力就没有那么大了。
如下图:
针对Redis缓存实例发生故障宕机的情况,同样也有两点建议。
- 在业务系统中实现服务熔断或者请求限流机制:
- 服务熔断:在发生缓存雪崩时,为了防止引发连锁的数据库雪崩,甚至是整个系统的崩溃,我们暂停业务应用对缓存系统的接口访问。
- 请求限流:在请求入口前端只允许每秒进入系统的请求数为 1000 个,再多的请求就会在入口前端被直接拒绝服务。
- 提前预防。通过主从节点的方式构建 Redis 缓存高可靠集群。如果 Redis 缓存的主节点故障宕机了,从节点还可以切换成为主节点,继续提供缓存服务,避免了由于缓存实例宕机而导致的缓存雪崩问题。
如下图:
【注:服务熔断虽然可以保证数据库的正常运行,但是暂停了整个缓存系统的访问,对业务应用的影响范围大。为了尽可能减少这种影响,可以使用请求限流的方式。】
缓存穿透
缓存穿透指的是要访问的数据既不在Redis中,也不在数据库中,导致请求访问缓存缓缺失,访问数据库而数据库也无数据。这样一来应用无法从数据库中读取写入缓存,缓存成了摆设,同时给数据库和缓存都带来巨大的压力。
如下图:
产生原因
- 业务层误操作:缓存中的数据和数据库中的数据被误删除了,所以缓存中和数据库中都没有数据。
- 恶意攻击:专门访问数据库中没有数据。
解决方案
提供三种解决方案
缓存空值或者缺省值。
一旦发生缓存穿透,可针对查询的数据在redis缓存中存一个空值或者缺省值,当应用发送后续请求进行查询的时候就可以从redis中读取到空值或者缺省值返回,避免大量请求数据库。
使用布隆过滤器快速判断数据是否存在,避免从数据库中查询数据,减轻数据库压力
通过查询布隆过滤器快速判断数据是否存在,如果不存在就不需要再去数据库中查询了。
在请求入口的前端进行请求检测。
缓存穿透很大一部分原因是有大量的恶意请求访问不存在的数据,所以对业务系统接收到的请求进行合法性检测,把恶意的请求直接过滤掉,不让它们访问后端缓存和数据库。
跟缓存雪崩、缓存击穿这两类问题相比,缓存穿透的影响更大一些。从预防的角度来说,我们需要避免误删除数据库和缓存中的数据;从应对角度来说,我们可以在业务系统中使用缓存空值或缺省值、使用布隆过滤器,以及进行恶意请求检测等方法。
扩展
布隆过滤器
定义
每布隆过滤器(Bloom Filter)是一个很长的二进制向量数组和一系列随机映射函数,用于检索一个元素是否在一个集合中
优缺点
优点:
- 时间复杂度低,增加和查询元素的时间复杂度为O(N)(N为hash函数个数,通常情况下比较小)
- 保密性强,因为布隆过滤器不存储元素本身。
- 存储空间小。
缺点:
- 有一定的误判率,但是可以通过调整参数来降低
- 无法获取元素本身
- 很难删除元素
工作原理
布隆过滤器的工作原理就是首先多个无偏hash函数把元素的hash值计算出来,这些hash值再对二进制数组的长度取模,得到每个hash值在数组中的对应位置,最后把对应位置的值设为1,完成标记。
如果数据不存在,也就是没有用布隆过滤器标记过,则二进制数组对应位置为零。
- 二进制数组
- hash函数计算元素的hash值,计算后的元素下标比较均匀的映射到位数组中
比如增加一个元素。
过程为:
- 通过k个无偏hash函数计算得到k个hash值
- 依次取模数组长度,得到数组索引
- 将计算得到的数组索引下标位置数据修改为1
如图:
【这样关于误判其实就很好理解了,hash函数再怎么好也无法完全避免hash冲突,也就是说有可能存在多个元素计算hash值为相同的,取模数组长度后的数组索引也是相同的,这就是误判的原因】
提供一个布隆过滤器在线计算网址:
https://krisives.github.io/bloom-calculator/
使用场景
- 解决Redis缓存穿透问题
- 做邮件的黑名单过滤
- 对爬虫网址做过滤,爬过的不在爬
- 解决新闻推荐过的不再推荐
- HBase/RocksDB/LevelDB等数据库内置布隆过滤器,用于判断数据是否存在,可以减少数据库的IO请求
Redis集成布隆过滤器
用Redis可以集成布隆过滤器,版本推荐6.x,最低4.x版本,下载安装插件后在redis.config配置文件中加入redisbloom.so文件的地址并重启。(若是redis集群则每个配置文件中都需要加入redisbloom.so文件的地址)
主要指令有:
- bf.add 添加一个元素
- bf.exists 判断一个元素是否存在
- bf.madd 添加多个元素
- bf.mexists 判断多个元素是否存在
[Redis] Redis的三大缓存异常原因分析和解决方案的更多相关文章
- 修改List报ConcurrentModificationException异常原因分析
使用迭代器遍历List的时候修改List报ConcurrentModificationException异常原因分析 在使用Iterator来迭代遍历List的时候如果修改该List对象,则会报jav ...
- IP访问频率限制不能用数组循环插入多个限制条件原因分析及解决方案
14.IP频率限制不能用数组循环插入多个限制条件原因分析及解决方案: define("RATE_LIMITING_ARR", array('3' => 3, '6' => ...
- hive on spark:return code 30041 Failed to create Spark client for Spark session原因分析及解决方案探寻
最近在Hive中使用Spark引擎进行执行时(set hive.execution.engine=spark),经常遇到return code 30041的报错,为了深入探究其原因,阅读了官方issu ...
- Oracle包被锁定的原因分析及解决方案
http://blog.csdn.net/jojo52013145/article/details/7470812 在数据库的开发过程中,经常碰到包.存储过程.函数无法编译或编译时会导致PL/SQL ...
- CMMI5级——原因分析及解决方案(Causal Analysis and Resolution)
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010825142/article/details/15338085 聪明的人在出现问题的时候,除了 ...
- SQL查询速度慢的原因分析和解决方案
SQL查询速度慢的原因分析和解决方案 查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建 ...
- Beforeunload打点丢失原因分析及解决方案
淘宝的鱼相在 2012 年 8 月份发表了一篇文章,里面讲述了他们通过一个月的数据采集试验,得到的结果是:如果在浏览器的本页面刷新之前发送打点请求,各浏览器都有不同程度的点击丢失情况,具体点击丢失率统 ...
- 关于JVM内存溢出的原因分析及解决方案探讨
前言:JVM中除了程序计数器,其他的区域都有可能会发生内存溢出. 0.什么是内存溢出 当程序需要申请内存的时候,由于没有足够的内存,此时就会抛出OutOfMemoryError,这就是内存溢出. 1. ...
- 在Android library中不能使用switch-case语句访问资源ID的原因分析及解决方案
转自:http://www.jianshu.com/p/89687f618837 原因分析 当我们在Android依赖库中使用switch-case语句访问资源ID时会报如下图所示的错误,报的错误 ...
- window.open浏览器弹出新窗口被拦截—原因分析和解决方案
最近在做项目的时候碰到了使用window.open被浏览器拦截的情况,在本机实验没问题,到了服务器就被拦截了,火狐有拦截提示,360浏览器拦截提示都没有,虽然在自己的环境可以对页面进行放行,但是对用户 ...
随机推荐
- 关闭 cockpit 登陆提示
sudo rm /etc/issue.d/cockpit.issue sudo rm /etc/motd.d/cockpit
- 机器学习-线性分类-支持向量机SVM-合页损失-SVM输出概率值-16
目录 1. SVM概率化输出 2. 合页损失 1. SVM概率化输出 标准的SVM进行预测 输出的结果是: 是无法输出0-1之间的 正样本 发生的概率值 sigmoid-fitting 方法: 将标准 ...
- keystore 与 trust store 的区别 及 keytool 常用命令
本文为博主原创,未经允许不得转载: 1. key store 与 trust store 区别 2. java 配置 单向认证与双向认证的过程 3. key store 与 trust store 常 ...
- kafka 的基本概念及使用场景
本文为博主原创,未经允许不得转载: 1. Kafka 的使用场景: 1.日志收集:一个公司可以用Kafka收集各种服务的log,通过kafka以统一接口服务的方式开放给各种 consumer,例如ha ...
- Git-历史版本切换-log-reset
- Go-获取指定长度随机字符串
// GetCode 获取一个随机用户唯一编号 func GetCode(codeLen int) string { // 1. 定义原始字符串 rawStr := "abcdefghijk ...
- 配置Chrome支持网页内的frame跨域
前言 跨域限制可以保证安全,但是调试的时候关掉会更方便,然而现在网络上能找到的关闭跨域限制方法,在新版的Chrome浏览器上根本没用-- 经过一番摸索,发现用旧版的Chrome就可以绕过跨域限制,刚好 ...
- [转帖]Linux fsync和fdatasync系统调用实现分析(Ext4文件系统)
转自:https://blog.csdn.net/luckyapple1028/article/details/61413724 在Linux系统中,对文件系统上文件的读写一般是通过页缓存(pag ...
- [转帖]InfluxDB 修改数据存储路径
1.创建数据存储目录 mkdir -p /home/data/influxdb 说明:目录可以根据实际情况进行修改. 2.设置目录访问权限 sudo chown influxdb.influxdb / ...
- [转帖]命令行非明文密码连接 TiDB
https://tidb.net/blog/6794a34b#%E6%96%B9%E5%BC%8F%E4%B8%80%EF%BC%9A%E5%91%BD%E4%BB%A4%E8%A1%8C%E8%BE ...