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 缓存异常、应对策略的更多相关文章

  1. Redis缓存异常的容错实现方法( .net)

    using DotNet.Log; /// <summary> /// Redis缓存辅助类 /// /// 修改纪录 /// /// 2015-10-26 版本:1.0 SongBiao ...

  2. redis 缓存用户账单策略

    最近项目要求分页展示用户账单列表,为提高响应使用redis做缓存,用到的缓存策略和大家分享一下. 需求描述:展示用户账单基本信息以时间倒序排序,筛选条件账单类型(所有,订单收入.提现.充值...). ...

  3. 第三方网站返回hybrid app H5页面缓存问题应对策略

    最近负责公司各产品线购买模块的开发,各项功能如期开发完成后测试那边反馈回来一个问题:IOS手机在点击支付宝购买后,跳转到支付宝网站时不输入支付密码,直接点返回,返回到我们自己的APP购买界面发现页面显 ...

  4. Redis总结(五)缓存雪崩和缓存穿透等问题 Web API系列(三)统一异常处理 C#总结(一)AutoResetEvent的使用介绍(用AutoResetEvent实现同步) C#总结(二)事件Event 介绍总结 C#总结(三)DataGridView增加全选列 Web API系列(二)接口安全和参数校验 RabbitMQ学习系列(六): RabbitMQ 高可用集群

    Redis总结(五)缓存雪崩和缓存穿透等问题   前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhon ...

  5. Redis缓存篇(四)缓存异常

    这一节,我们来学习一下缓存异常.缓存异常有四种类型,分别是缓存和数据库的数据不一致.缓存雪崩.缓存击穿和缓存穿透. 下面通过了解这四种缓存异常的原理和应对方法. 缓存和数据库的数据不一致 缓存和数据库 ...

  6. 转:Redis 缓存策略

    转:http://api.crap.cn/index.do#/web/article/detail/web/ARTICLE/7754a002-6400-442d-8dc8-e76e72d948ac 目 ...

  7. Redis总结(五)缓存雪崩和缓存穿透等问题

    前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhong/category/771056.html .今 ...

  8. redis 缓存策略

    redis 缓存策略配置项:maxmemory <bytes>maxmemory-policy noeviction 触发时机:每次执行命令(processCommand)的时候会检测 w ...

  9. Redis总结(五)缓存雪崩和缓存穿透等问题(转载)

    前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhong/category/771056.html .今 ...

  10. Redis缓存策略设计及常见问题

    Redis缓存设计及常见问题 缓存能够有效地加速应用的读写速度,同时也可以降低后端负载,对日常应用的开发至关重要.下面会介绍缓存使用技巧和设计方案,包含如下内容:缓存的收益和成本分析.缓存更新策略的选 ...

随机推荐

  1. JavaScript 实现前端文件下载

    A.download HTML5的A标签有一个download属性,可以告诉浏览器下载而非预览文件,很实用,参考链接:http://www.zhangxinxu.com/wordpress/2016/ ...

  2. C++ 类的继承(Inheritance)

    一.继承(Inheritance) C++有一个很好的性质称为inheritance(继承),就是声明一个class(derived class),把另一个或多个class(base class)的所 ...

  3. 使用IIS部署WebDAV

    服务器开启WebDAV 在服务器安装IIS的同时 要启用Windows身份验证与WebDAV发布 如果不是服务器版本,参照下图 在IIS中新建WebDAV网站 配置好本地目录与端口 启用Windows ...

  4. redis持久化存储数据(rdb和aof)

    rdb持久化存储数据 总的 redis持久化 防止数据丢失,持久化到本地,以文件形式保存 持久化的方式 ,两种 aof和 rdb模式 1.触发机制, - 手动执行save命令 - 或者配置触发条件 s ...

  5. WPF登录界面样例

    XAML文件内容如下 1 <Window x:Class="ERP.Views.Login" 2 xmlns="http://schemas.microsoft.c ...

  6. 【题解】A18747.眼红的同学

    题目链接:眼红的同学 题干信息很简单,看到数据量之后就不简单了.在数据量小的时候可以使用双层循环暴力的方法来求答案.显然对于这道题而言O(n^2)是完全过不去的. 前置知识: 使用树状数组求逆序对 会 ...

  7. 工作面试老大难-MySQL中的锁类型

    MySQL 是支持ACID特性的数据库.我们都知道"C"代表Consistent,当不同事务操作同一行记录时,为了保证一致性,需要对记录加锁.在MySQL 中,不同的引擎下的锁行为 ...

  8. Swoole 源码分析之 Timer 定时器模块

    原文首发链接:Swoole 源码分析之 Timer 定时器模块 大家好,我是码农先森. 引言 Swoole 中的毫秒精度的定时器.底层基于 epoll_wait 和 setitimer 实现,数据结构 ...

  9. Qt-qrencode开发-生成、显示二维码📀

    Qt-qrencode开发-生成二维码 目录 Qt-qrencode开发-生成二维码 1.概述 2.实现效果 3.编译qrencode 4.在QT中引入编译为静态库的QRencode 5.在Qt中直接 ...

  10. Linu部署服务启停脚本

    Linux项目部署启停 WEB应用(WAR包)部署 实际开发中,难免遇见新业务项目构建.项目重构(重新优化整个项目的架构,相当于重写),也可能是项目拆分多个模块,也可能部分拆分,但项目的模块化分离,就 ...