Redis缓存穿透、缓存雪崩、缓存击穿好好说说

前言

Redis是目前非常流行的缓存数据库啦,其中一个主要作用就是为了避免大量请求直接打到数据库,以此来缓解数据库服务器压力;用上缓存难道就高枕无忧了吗?no,no,no,没有这么完美的技术, 缓存穿透、缓存雪崩、缓存击穿这些问题都得好好聊聊。

正文

1. 缓存穿透

1.1 简要描述

缓存穿透是指查找的数据在缓存和数据库中都不存在,导致每一次请求数据从缓存中都获取不到,而将请求打到数据库服务器,但数据库中也没有对应的数据,最后每一次请求都到数据库;如果在高并发场景或有人恶意攻击,就会导致后台数据库服务器压力增大,最终系统可能崩掉。来个直接点的图:

简要说明:

缓存Redis服务器颜色说明:绿色块代表有缓存数据,粉色块代表缓存中没有数据;绿色箭头代表直接从缓存中获取数据;黄色箭头代表穿过缓存从数据库中查数据,但不一定有。

流程大概如下:

  1. 大量客户端发起大量请求到服务器;

  2. 服务器代码逻辑将先经过缓存,如果有缓存数据(绿色部分),直接从缓存中获取数据数据返回;如果缓存中没有数据(粉色部分),请求就会直接打到数据库服务器(如黄色箭头)。

  3. 如果存在大量无缓存数据的请求,最终数据库将因为过大压力而崩掉,导致系统不可用。

1.2 常用解决措施
  • 缓存空值:如果没有在数据库中获取到数据,可以将其对应键的空值进行缓存,并设置较短过期时间;

    优点:在过期时间内直接通过缓存返回空值;从而避免数据库压力;

    缺点:

    消耗Redis内存:如果是攻击者换着非常规的键值请求,如果每次都缓存到Redis中,大量的空数据也占内存空间;

    数据不一致:如果是正常数据,刚开始没有数据,然后将空值进行缓存,并设置短暂的过期时间;如果在过期时间内正常维护了对应的数据,此时取到值仍是空,并没有去数据库中获取新维护数据,导致数据获取不一致。

  • 布隆过滤器

    加一层过滤器进行拦截,判断请求对应的键是否在过滤器中,如果不在就直接返回,不去请求数据库,也不用缓存空值。而布隆过滤器采用bit位的形式标识对应键(每个键进行Hash过后都会得到具体的位置)是否存在,可以用极少的空间标识超大量的数据。

    缺点:布隆过滤器可以判断数据一定不在过滤器中,而对于存在的判断有误判率,因为Hash算法存在冲突的情况。

1.3 布隆过滤器

布隆过滤器不是专门用来针对缓存穿透的,它的应用场景很多,比如避免邮件重发、爬虫软件重爬、视频推送重复等;可能有的小伙伴还不明白为什么可以这么用,那先简单说说布隆过滤器的原理。

瞅个图先:

简要说明:

  1. 先来一个Key,后续需要判断Key是否存在(这里Key可以是任意想存的数据,比如用户ID、视频标识等);

  2. 将Key进行多次hash计算;每次的hash算法得到的结果都不一样;上图只画了三次hash计算,其实实际根据误判率不一样,hash次数就不一样;

  3. 将hash结果对应下标索引的bit位改为1,表示存在;上图经过三次hash,结果分别为2、5、9,则将对应的位置改为1;

  4. 如果需要判断Key是否在过滤器中,同样需进行多次hash计算,上图为三次,将计算出来的结果作为索引去获取对应的标识,三次中只要有一次对应位置的值为0,那就证明Key不存在过滤器中。如果是判定存在,则三次的结果对应位置的值应该都为1,不过这样是有误判可能,因为不同的Key,hash的结果有可能是一样的,从而就导致设置对应索引位时就会有冲突,如下图;


    先假设Key1、Key2经过三次hash的结果一样(实际场景是存在的),倘若Key1先来都将2、5、9位置的值设为1,那Key2进来判断存在时,由于hash的结果一样,从而就误判为在过滤器中,其实不存在;

    误判率在布隆过滤器中是可以控制,如果需要降低误判率,那就多进行几次hash计算,那位置相同的概率就降低啦;但这样会影响效率,另外也会有内存的额外开销,hash次数多,需要标识的位就越多。就算有误判率,也很小,在绝大多数场景下可接受。

1.4 布隆过滤器的使用

既然说Redis,就说Redis的布隆过滤器吧,其实小伙伴可以根据自己的需求利用Redis的bitmap实现。那有没有造好的轮子呢,当然有,在Redis4.0开始就有一个布隆过滤器的组件,开箱即用,当然也有一些其他大佬封装的,基于内存的,基于分布式都有。这里简单说说Redis布隆过滤器的插件,个人觉得挺好的,推荐哦。

官方文档地址:https://oss.redislabs.com/redisbloom/

我这面是用centos进行演示,主要步骤如下:

  1. 如果没有git的需要安装一下;如果不用git就去下载代码压缩包;

    yum install -y git
    
  2. 把redis布隆过滤器的源码搞下来,这里用git;也可以通过下载的方式;

    git clone https://github.com/RedisLabsModules/redisbloom.git
    
  3. 进入代码目录进行make(生成redisbloom.so文件),如果make命令找不到,就需要安装VC++编译相关的包;

    cd redisbloom
    make
    
  4. 在Redis配置文件中配置加载redisbloom插件,然后重启就可以用啦;也可以启动的时候指定加载插件运行;

    配置文件方式:在配置文件中添加如下配置,需要指定redisbloom.so具体的文件位置。


    然后指定配置文件启动即可;

    ./redis-server redis.conf
    启动时指定模块运行方式:
    
    ./redis-server --loadmodule ./redisbloom.so
  5. 简单使用


    命令使用和常规命令一样啦,就不需要我再写程序了吧,如果非要的话,那就简单说两句:

    A.将需要判断数据保存在过滤器中,比如所有的用户id;

    B.当请求过来时就先从过滤器中判断有无数据,没有直接返回,不去缓存,也不去数据库;

    C.如果有新添加的用户,需要将新的用户id放到过滤器中;

关于Redis布隆过滤器还有一些命令没说,小伙伴可以去逛逛官网。有小伙伴肯定会问,不用这个插件行吗,当然行啊,可以自己实现嘛,不过有些小伙伴有封装好的包啦,有基于内存的,也有基于Redis的,如下图:

代码我就不上了,剩下的就留给小伙伴啦。

2. 缓存雪崩

1.1 简要描述

缓存雪崩是指突然缓存层不可用,导致大量请求直接打到数据库,最终由于数据库压力过大可能导致系统崩掉。缓存层不可用指以下两方面:

  • 缓存服务器宕机,系统将请求打到数据库;

  • 缓存数据突然大范围集中过期失效,导致大量请求打到数据库重新加载数据;

如图:

简要说明:

缓存Redis服务器颜色说明:绿色块代表有缓存数据,粉色块代表缓存中没有数据;白色块代表大范围失效的缓存数据,绿色箭头代表直接从缓存中获取数据;黄色箭头代表穿过缓存从数据库中查数据。

流程大概如下:

  1. 大量客户端发起大量请求到服务器;

  2. 服务器代码逻辑将先经过缓存,如果有缓存数据(绿色部分),直接从缓存中获取数据数据返回;如果缓存过期(白色块部分),请求就会直接打到数据库服务器(如黄色箭头)

  3. 如果存在大量热数据的请求,但热数据又大范围过期,最终数据库将因为过大压力崩掉,导致系统不可用。

1.2 常用解决措施
  • 缓存预热:在高峰期还没到来时,提前将热数据加载到缓存中,避免高峰期来临时数据库压力过大。

  • 均匀设置过期时间:针对不同的热点数据,将过期时间加上一个随机值,让过期时间不集中在一个点,从而减小很大部分数据库压力;

  • 多级缓存:除了使用Redis缓存,还可以根据业务增加一些热点数据的其他缓存,比如内存缓存,可以将各级的缓存有效期分开,这种方式也能缓解数据库的压力;

  • 限流、降级:如果压力过大,避免把系统搞崩,可以增加一些限流手段,不管是中间件还是消息队列等,主要保证系统的可用。

  • 加互斥锁:目的就是加锁独占操作,让一个操作向缓存中重新加载数据,让请求操作等待,其实这样的体验不好,慎用。如果要用,要超级注意锁的性能和稳定性。

  • 对于缓存层整体崩掉的情况:使用高可用架构,比如之前说到的主从复制、哨兵、集群,根据需求进行对应架构,保证缓存层不崩掉。

3. 缓存击穿

1.1 简要描述

缓存击穿是指在超级热点数据突然过期,导致针对超级热点的数据请求在过期期间直接打到数据库,这样数据库服务器会因为某一超热数据导致压力过大而崩掉。

超热数据:比如秒杀时的数据,某宝、某东、某多多这种平台的数据如果在秒杀时间段失效,请求量足矣让数据库崩掉。

如图:

简要说明:

缓存Redis服务器颜色说明:绿色块代表有缓存数据,粉色块代表缓存中没有数据;白色圈代表超级热点缓存数据过期失效,绿色箭头代表直接从缓存中获取数据;黄色箭头代表穿过缓存从数据库中查数据。

流程大概如下:

  1. 大量客户端发起大量请求到服务器;

  2. 服务器代码逻辑将先经过缓存,如果有缓存数据(绿色部分),直接从缓存中获取数据数据返回;如果超热缓存数据过期(白色圈部分),请求就会直接打到数据库服务器(如黄色箭头)

  3. 超级热点数据过期失效,如秒杀数据,如果在秒杀时段失效,最终数据库将因为过大压力崩掉,导致系统不可用。

注:这个只是针对超热点数据,而不是大范围数据。

1.2 常用解决措施
  • 热点数据不过期:像这种超热数据就设置永不过期。避免过期失效让数据库压力过大而崩。

  • 加互斥锁:目的就是加锁,然后向缓存中重新加载数据,让请求等待,其实这样的体验不好,慎用。如果要用,要超级注意锁的性能和稳定性。

总结

缓存穿透、缓存雪崩、缓存击穿不管是哪个问题,其主要原因还是在缓存层没有命中,将请求直接打到数据库啦,最终导致数据库压力过大,系统不可用。小伙伴根据系统需要进行问题处理,没有完美的解决方案,但总会有一种适合需求的方案,解决业务问题才是真正目的。

今天没有上代码,相信小伙伴都能根据解决措施写出对应的代码,分布式锁可能稍微有点难搞,下次抽时间给大家安排上。

关于Redis系列,下篇说说Lua脚本就算初步完成啦,剩下的就是实战的总结啦,在项目的使用过程中,如果有好的方案和棘手的问题都会和小伙伴分享。接下来数据库优化系列即将开启,主要针对MySql。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/304457.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

这是“我”的故事 —— 董彬

点击蓝字 关注我们作者:董彬校对/文章优化:刘轶民排版:Rani视频地址:https://www.bilibili.com/video/BV1NK4y1p7Ys与世界周旋的程序员大家好,我叫董彬 ,现就职于野村信息, Title 是 Senior …

我用Python玩小游戏“跳一跳”,瞬间称霸了朋友圈!

“从前几天微信最新版本 6.6.1 的更新开始,微信小程序游戏“跳一跳”似乎在一夜之间风靡了朋友圈。它甚至比五六年前的飞机大战游戏都火爆,这种小游戏的火爆不仅仅是因为有魔性、有意思,更重要的是可以进行好友 PK!“跳一跳”的小…

expsky.php,Typecho漏洞利用工具首发,半分钟完成渗透

原标题:Typecho漏洞利用工具首发,半分钟完成渗透*本文原创作者:expsky,本文属FreeBuf原创奖励计划,未经许可禁止转载声明:本工具由expsky原创,仅用于技术研究,不恰当使用会对网站造成…

BeetleX之Web网关1.5.7安装使用

新版的网关主要升级到BeetleX最新版提高http协议的解释性能,从而让网关的吞吐能力进一步提升,在功能界面上也做了简单的调整让操作更方便,修复linux下无权限启动进程问题。如果在windows上不想用IIS,linux下用nginx怕麻烦&#xf…

费马大定理,集惊险与武侠于一体

悬案费马大定理从提出到证明的过程,就是一部不折不扣的惊险小说。一个读者,在自己看过的书空白处留下附注。除了他自己,还有谁会关注呢?但是,法国人费马死后,他在一本《算术》书上所写的注记并没有随之湮没…

全国计算机技术与软件专业技术资格(水平)考试基础知识

全国计算机技术与软件专业技术资格(水平)考试基础知识 -------------------------------------------------------------------------------- 1、什么是计算机技术与软件专业技术资格(水平)考试?  计算机技术与软件专…

GPU迎来投资热潮 退潮后谁在裸泳

近期,数家GPU设计公司获得资本青睐,摩尔线程完成数轮投资获得数十亿元,无独有偶,壁仞科技宣布完成总额11亿元的A轮融资,沐曦集成电路宣布完成近亿元天使轮融资,登临科技宣布完成A轮融资。另外,天…

All in AI, 一句话看出了百度的野心,也看到了人工智能人才的未来

最近几天,在 2018 CES科技盛会上,百度无人驾驶系统 Apollo 2.0 正式开放,百度COO 陆奇表示,借着 Apollo 平台,他想打造中国无人车国家队!All in AI, 一句话看出了百度的野心。而百度,只是 China…

知名Node.js组件存在代码注入漏洞

喜欢就关注我们吧!日前,一个被大量下载的 Node.js 组件被发现其含有一个高危的代码注入漏洞。该漏洞被追踪为 CVE-2021-21315,影响了「systeminformation」npm 组件的安全性,该组件每周的下载量约为 80 万次,自诞生以来…

VPC2007差分硬盘让小硬盘也能跑多个虚拟机

在Winos中看到http://bbs.winos.cn/thread-43391-1-1.html于 2008-9-2 16:02 发表基于Vmware Workstation 让你的小硬盘也能跑多个虚拟机个人认为有些做得不是很人性化。比如说我要把虚拟机母板封装好之后要修改为只读,而且还要隐藏起来。那么我再要创建虚拟机就要…

2017新生儿爆款名字出炉!90后的父母们最受欢迎的居然是.....

名字跟随一生因此很多家长在给孩子起名字的时候都相当谨慎除了日常迷信外不重名成为取名的重要考虑因素学校走廊里喊一声“子涵”,竟有3人回头!!你知道你家孩子的名字和多少人重名了吗?近日,江苏苏州一家科技公司发布《…

Kubernetes中分布式存储Rook-Ceph的使用:一个ASP.NET Core MVC的案例

在《Kubernetes中分布式存储Rook-Ceph部署快速演练》文章中,我快速介绍了Kubernetes中分布式存储Rook-Ceph的部署过程,这里介绍如何在部署于Kubernetes的ASP.NET Core MVC的应用程序中使用Rook-Ceph所创建的存储对象。构建ASP.NET Core MVC (.NET 5)应用…

在Windows上安装Docker

背景Windows的Docker桌面是Microsoft Windows的Docker的社区版本。您可以从Docker Hub下载适用于Windows的Docker桌面。该页面包含有关在Windows 10 Pro,Enterprise和Education上安装Docker Desktop的信息。如果要查找有关在Windows 10 Home上安装Docker桌面的信息.…

全景图解高铁数据,谁是最有潜力的高铁城市?

经过十年的快速发展,高铁已成为人们日常出行的重要交通工具,“千里江陵一日还”早已变成现实,高铁改变的不仅是不断刷新的“中国速度”,更为区域与城市发展带来新的模式与机遇。高铁以高速、大容量、集约型、通勤化的特征&#xf…

原型链的理解_javascript之快速理解(原型链)

希望通过比较通俗易懂的讲解和简短的文字,让大家能快速理解什么是原型链,如果有不对的地方也请各位大佬快速纠正,一起共勉,使我们初学者快速进阶!话不多说,我们切入正题,按着我的步骤一步一步往…

如何轻松将上亿的数据玩弄于股掌之中?

在日常生活中,我们经常会遇到排序问题:在打扑克牌的时候,原本拿到手上的牌是乱序的,我们会按照自己喜好的顺序一张一张排好手上的牌,最后看起来是顺眼的。比如小智打扑克牌会将自己手上的牌排成这样:小智排…

php webshell开源,[github开源]webshell连接器--Jeshell

前言:以前连接webshell都是用一个好朋友写的Webshellsniper,但是昨天使用webshellsniper测试的时候,发现不能支持shell_exec()这个php函数,问了一下才知道,他写的默认是只用eval()和assert()函数的webshell。于是&…

IT人的八大修炼神器

看到2018年的KPI,你是否感到崩溃?在这个充满竞争的时代,你需要用最有效的方式,学习最有用的知识,来提高自身技能。小编特意为大家准备IT人的八大修炼神器,推荐能帮助我们提升技术的公众号,欢迎大…

hotelling t2 matlab,pca主成份分析方法

1.应用pca的前提应用pca的前提是,连续信号具有相关性。相关性是什么,是冗余。就是要利用pca去除冗余。2.pca的定义pca是一种去除随机变量间相关性的线性变换。是一种常用的多元数据分析方法。pca将互相关的输入数据转换成统计上不相干的主成分(或者特征)…

如何在 WebAPI 中启用 CORS

浏览器安全策略上的安全限制可以有效的阻止 Ajax 向另外一个域server发起请求,这就是著名的 同源策略,那如何突破这种限制呢?可以使用 CORS (Cross-Origin Resource Sharing) 跨域资源共享来解决此类问题,它…