(五)Redis 缓存异常、应对策略
1、缓存和数据库不一致
只要我们使用 Redis 缓存,就必然会面对缓存和数据库间的一致性保证问题,这里的“一致性”包含了两种情况:缓存中有数据且与数据库中的值相同、缓存中没有数据,最新值在数据库中。
对于读写缓存来说,要想保证缓存和数据库中的数据一致,就要采用同步直写策略,在业务应用中使用事务机制,来保证缓存和数据库的更新具有原子性。对数据一致性的要求不高的场景,可以使用异步写回策略。
只读缓存在新增数据时是符合数据一致性第二种情况的,但是在删改数据时,无论是操作缓存还是操作数据库,有一项失败,就会产生数据不一致的问题。具体情况如图:
针对这种情况可以引用重试机制来解决,具体来说,可以把要数据暂存到消息队列中。无论哪项操作失败,都可以从消息队列中重新读取这些值,然后再次进行删除或更新。如果删改成功,就把数据从消息队列中去除,以免重复操作,以此来保证数据一致性。多次重试仍然失败的话就需要业务层面预警来排查解决了。
除了操作失败的原因,实际当有大量并发请求时,应用还是有可能读到不一致的数据。根据删改缓存、数据库的先后顺序分为两种情况:先操作缓存和先操作数据库。通过引用“延迟双删”的操作,来保证先操作缓存后操作数据库的数据一致性问题,代码示意如下:
redis.delKey(X)
db.update(X)
Thread.sleep(N)
redis.delKey(X)
具体情况与应对措施总结如图:

2、雪崩
指大量的应用请求无法在 Redis 缓存中进行处理,到达数据库层面,导致数据库的压力激增。原因有二:
其一,缓存中有大量数据同时过期。
其二,Redis 缓存实例挂了。
原因一可以通过以下两个方法解决:
(1)微调过期时间:对于同一批数据设置不同的过期时间,如通过随机数延迟过期等。
(2)降级处理:非核心数据请求直接返回 空 或 错误 等预置信息,核心数据运行未命中缓存访问数据库。

原因二可以通过以下两个方法解决:
(1)熔断:拒绝缓存客户端的请求,保护数据库,防止整个系统崩溃,直到 Redis 缓存实例恢复正常,但是对业务应用的影响范围大。
(2)限流:允许部分请求到达 Redis 缓存,无法命中再访问数据库,减轻数据库压力,相对于熔断来说影响范围稍微缩小。
无论采取何种措施,雪崩都已经发生了,必定会影响到业务系统,所以要做好预防工作,构建 Redis 缓存高可靠集群,尽量避免事故。
3、击穿
指针对某个热点数据的请求,无法在缓存中处理,大量访问该数据的请求发送到了后端数据库,压力激增影响到其他请求,如下图:
为了避免缓存击穿给数据库带来的激增压力,对于访问特别频繁的热点数据,可以不设置过期时间了,全部在缓存中进行处理。

4、穿透
指要访问的数据既不在 Redis 缓存中,也不在数据库中,导致请求压力还是落到数据库,缓存也就成了“摆设”。如下图:
通常情况是由于业务数据被误删除,或者恶意攻击访问,有三种方案解决缓存穿透的影响:
(1)缓存空值或缺省值:针对穿透的数据,在 Redis 中缓存一个空值或是和业务层协商确定的缺省值,避免把大量请求发送给数据库。
(2)布隆过滤器
布隆过滤器由一个初值都为 0 的 bit 数组和 N 个哈希函数组成,数据入库则进行标记,过程如下:
- 使用 N 个哈希函数,分别计算这个数据的哈希值,得到 N 个哈希值。
- 我们把这 N 个哈希值对 bit 数组的长度取模,得到每个哈希值在数组中的对应位置。
- 我们把对应位置的 bit 位设置为 1,这就完成了在布隆过滤器中标记数据的操作。
当查询某个数据时,按照哈希函数的计算结果,查看 bit 数组中这 N 个位置上的 bit 值,只要有一个不为 1,这就表明布隆过滤器没有对该数据做过标记。当缓存穿透发生,布隆过滤器的快速检测特性可以帮数据库阻挡大部分的压力。例子如下图:
(3)前端请求过滤:在请求入口前端进行合法性检测,把恶意的请求(如请求参数不合理、非法值或请求字段不存在)直接过滤掉。
小结
雪崩、击穿、穿透,这三类异常问题从成因来看,前两个主要是因为数据不在缓存中了,而穿透则是因为数据既不在缓存中,也不在数据库中。当雪崩或击穿发生时,一旦数据库中的数据被再次写入到缓存后,应用又可以在缓存中快速访问数据了,数据库的压力也会相应地降低,而穿透发生时,Redis 缓存和数据库会同时持续承受请求压力。
对应的熔断、降级、限流这些方法都是属于“有损”方案,在保证数据库和整体系统稳定的同时,会对业务应用带来负面影响。降级时,有部分数据的请求就只能得到错误返回信息,无法正常处理。熔断时,整个缓存系统暂停,影响的业务范围更大。流机时,整个业务系统的吞吐率会降低,并发处理能力减弱,影响到用户体验。
所以,应当尽量使用预防式方案,总结如下:
- 雪崩,合理地设置数据过期时间,以及搭建高可靠缓存集群。
- 击穿,在缓存访问非常频繁的热点数据时,不要设置过期时间。
- 穿透,提前在入口前端实现恶意请求检测,或者规范数据库的数据删除操作,避免误删除。

(五)Redis 缓存异常、应对策略的更多相关文章
- Redis缓存异常的容错实现方法( .net)
using DotNet.Log; /// <summary> /// Redis缓存辅助类 /// /// 修改纪录 /// /// 2015-10-26 版本:1.0 SongBiao ...
- redis 缓存用户账单策略
最近项目要求分页展示用户账单列表,为提高响应使用redis做缓存,用到的缓存策略和大家分享一下. 需求描述:展示用户账单基本信息以时间倒序排序,筛选条件账单类型(所有,订单收入.提现.充值...). ...
- 第三方网站返回hybrid app H5页面缓存问题应对策略
最近负责公司各产品线购买模块的开发,各项功能如期开发完成后测试那边反馈回来一个问题:IOS手机在点击支付宝购买后,跳转到支付宝网站时不输入支付密码,直接点返回,返回到我们自己的APP购买界面发现页面显 ...
- Redis总结(五)缓存雪崩和缓存穿透等问题 Web API系列(三)统一异常处理 C#总结(一)AutoResetEvent的使用介绍(用AutoResetEvent实现同步) C#总结(二)事件Event 介绍总结 C#总结(三)DataGridView增加全选列 Web API系列(二)接口安全和参数校验 RabbitMQ学习系列(六): RabbitMQ 高可用集群
Redis总结(五)缓存雪崩和缓存穿透等问题 前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhon ...
- Redis缓存篇(四)缓存异常
这一节,我们来学习一下缓存异常.缓存异常有四种类型,分别是缓存和数据库的数据不一致.缓存雪崩.缓存击穿和缓存穿透. 下面通过了解这四种缓存异常的原理和应对方法. 缓存和数据库的数据不一致 缓存和数据库 ...
- 转:Redis 缓存策略
转:http://api.crap.cn/index.do#/web/article/detail/web/ARTICLE/7754a002-6400-442d-8dc8-e76e72d948ac 目 ...
- Redis总结(五)缓存雪崩和缓存穿透等问题
前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhong/category/771056.html .今 ...
- redis 缓存策略
redis 缓存策略配置项:maxmemory <bytes>maxmemory-policy noeviction 触发时机:每次执行命令(processCommand)的时候会检测 w ...
- Redis总结(五)缓存雪崩和缓存穿透等问题(转载)
前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhong/category/771056.html .今 ...
- Redis缓存策略设计及常见问题
Redis缓存设计及常见问题 缓存能够有效地加速应用的读写速度,同时也可以降低后端负载,对日常应用的开发至关重要.下面会介绍缓存使用技巧和设计方案,包含如下内容:缓存的收益和成本分析.缓存更新策略的选 ...
随机推荐
- uni-app上使用leaflet地图的解决方案
在uni-app上自带有map组件,但是那个组件功能太弱,很多高级用法很难实现.用npm添加leaflet呢,又各种报错. 偶然和朋友聊起,可以用html来实现leaflet地图,然后用webview ...
- 基于Ubuntu20.04在k8s 1.25部署gin+MySQL服务
0. 前言 某天突发奇想,既然都学了 docker 了,那干脆,顺便把 kubernetes 也学了,于是开始了我长达一个月的环境搭建.踩坑历程. 最开始,我的想法是,在我的物理机使用 WSL + d ...
- Android 13 - Media框架(5)- NuPlayerDriver
关注公众号免费阅读全文,进入音视频开发技术分享群! 前面的章节中我们了解到上层调用setDataSource后,MediaPlayerService::Client(IMediaPlayer)会调用M ...
- 来自多彩世界的控制台——C#控制台输出彩色字符画
引言 看到酷安上有这样一个活动,萌生了用 C# 生成字符画的想法,先放出原图. 酷安手绘牛啤 §1 黑白 将图像转换成字符画在 C# 中很简单,思路大致如下: 加载图像,逐像素提取明度. ...
- .NET桌面程序混合开发之三:WebView2与JS的深度应用
在 WebView2 控件中使用 JavaScript 根据需求自由扩展原生应用的能力.本文探讨如何在 WebView2 中使用 JavaScript,并列举如何使用高级 WebView2 特性和功能 ...
- 莫烦tensorflow学习记录 (6)卷积神经网络 CNN (Convolutional Neural Network)
卷积 和 神经网络 莫烦大佬的原文章https://mofanpy.com/tutorials/machine-learning/tensorflow/intro-CNN/ 我的理解就是千层饼,鸡蛋烧 ...
- NOIP模拟81
T1 语言 解题思路 模拟即可,对于一个合法的句子直接判断每一个前缀和每一个后缀是否是合法的名词词组. 然后枚举动词的位置判断前后两段是否合法就好了. code #include<bits/st ...
- 电脑网卡把报文的vlan tag去掉
1 现象 现象说明:从电脑的网卡(用的Realtek)进来一个带vlan tag的报文,但是使用wireshark抓取的报文没有vlan tag. 解决方式如下:需要注册表. 参考链接1:https: ...
- numpy基础--利用数组进行数据处理
以下代码的前提:import numpy as np numpy数组可以将许多种数据处理任务表述为简洁的数组表达式,用数组表达式替换循环的做法,通常被称为矢量化. 官方说明文档:Array creat ...
- react css-in-js
CSS-in-JS是一种技术,而不是一个具体的库实现.简单来说CSS-in-JS就是将应用的CSS样式写在JavaScript文件里面,而不是独立为一些css,scss或less之类的文件,这样你就可 ...