缓存击穿、缓存穿透、缓存雪崩是使用Redis的三个经典问题,上篇文章讲了缓存击穿,今天就讲下剩下的两个问题。

一、缓存穿透

定义:缓存穿透是指查询一个根本不存在的数据,缓存层和DB层都不会命中。这样缓存永远不会生效,这些请求最终都会访问数据库。引起DB的压力瞬间变大,导致服务不可用。

问题:试想一个场景,正常来说,某个直播间的相关信息都是会缓存到Redis或者服务器的本地缓存中(提一嘴,我们有些并发量极高的数据是直接缓存在服务器的本地缓存中的,而不是缓存在Redis,因为Redis对于服务器来说是属于第三方组件,连接是耗时的,无论如何也比不过本地缓存。当然服务器本地缓存数据就需要每一台机器都缓存一份数据,就是空间换时间的概念,这个根据实际业务来衡量来采取哪种方案),而此时假设前端有一个异常请求,请求一个不存在的直播ID,那么我们首先会去查缓存,然后缓存没有,我们就会去查DB。好了,问题来了,假设前端伪造了N个这样的请求,那是不是N个请求都要去查DB,那么DB怎么可能扛得住啊。我们之前线上就出现过这样的问题,被恶意攻击了,血泪教训啊。

解决方案

解决缓存穿透问题有几种方案:

1、布隆过滤器。通过在前端部署一个布隆过滤器,可以预先判断该键很可能不存在于数据库中,然后将其拦截,从而避免对数据库发起无效请求。但是这玩意维护成本太高了,对于我们的业务来说,这很明显是还用不上的。感兴趣的同学可以去了解下,这里我就不细讲了。

2、对明显有问题的前端传参进行过滤,比如,假设直播ID是64长度的字符串,那么后端可以对不满足64位的请求直接给过滤掉,不处理。当然,这种小把戏自然是挡不住黑客的,人家搞一堆64位的字符串长度的直播ID不分分钟的事吗

3、设置空缓存,比如,虽然数据库中没有直播ID为“xxxx”的数据,但是在Redis中对其进行缓存(key=xxxx, value=null),这样当请求到达Redis的时候就会直接返回一个null的值给客户端,避免了大量无法访问的数据直接打在DB上。不过得注意,设置这种空缓存的时间不能设置过长,不然有恶意请求的时候,这种空缓存也会引起Redis存储空间暴涨。这个就是我们常用来处理缓存穿透问题的有效方案。 demo样例如下:

	rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "123456",
DB: 0,
}) err := rdb.Set(ctx, "xxxx", "null", 5*60).Err()
if err != nil {
panic(err)
}

二、缓存雪崩

定义:当Redis中的大量key集体过期或失效,这时候如果有大量并发的请求来到,Redis就无法进行有效的响应,所有的查询都落在数据库上,就会出现缓存雪崩。

问题:假设一个场景,我们的直播Redis机器在晚高峰时候出现了宕机,然后进行了重启,那么此时大量的前端请求就会进来,都会去读Redis。但是我重启之后,所以key值都被干掉了啊,那么这时所有的请求查Redis都得不到响应(太惨了),都需要重建缓存。这时候就会触发传说中的缓存雪崩(机器崩,人也差不多崩了)。当然,这是比较极端的一种场景。还有另一种情况就是使用了主动缓存(通过脚本或者定时任务等去生成缓存),然后设置的时间很集中,出现同时过期的时候,也会出现缓存雪崩问题。

解决方案

解决缓存雪崩问题有几种方案:

1、给缓存失效时间设置一些随机值,让缓存尽量的打散,不要集中在一个时间失效。其实大部分业务场景缓存时间都是打散的了,我们只需要使用的时候多留意一下即可。

2、使用Redis集群,当一台宕机之后,还有备用节点,可以将请求打到正常工作的节点中。

总的来说,缓存穿透和缓存雪崩问题带来的最终结果都是灾难性的,但是个人认为这两个在正常业务中,都是比较可控的,除非一些异常场景,例如被恶意攻击等行为。

go高并发之路——缓存穿透、缓存雪崩的更多相关文章

  1. redis的缓存穿透 缓存并发 缓存失效

    我们在用缓存的时候,不管是Redis或者Memcached,基本上会通用遇到以下三个问题: 缓存穿透 缓存并发 缓存失效 一.缓存穿透 Paste_Image.png Paste_Image.png ...

  2. Redis中几个简单的概念:缓存穿透/击穿/雪崩,别再被吓唬了

    Redis中几个“看似”高大上的概念,经常有人提到,某些好事者喜欢死扣概念,实战没多少,嘴巴里冒出来的全是高大上的名词,个人一向鄙视概念党,呵呵! 其实这几个概念:缓存穿透/缓存击穿/缓存雪崩,有一个 ...

  3. Java Redis缓存穿透/缓存雪崩/缓存击穿,Redis分布式锁实现秒杀,限购等

    package com.example.redisdistlock.controller; import com.example.redisdistlock.util.RedisUtil; impor ...

  4. Redis 17 缓存穿透 缓存击穿 缓存雪崩

    参考源 https://www.bilibili.com/video/BV1S54y1R7SB?spm_id_from=333.999.0.0 版本 本文章基于 Redis 6.2.6 使用缓存的问题 ...

  5. 缓存穿透 & 缓存击穿 & 缓存雪崩

    参考文档: 缓存穿透和缓存失效的预防和解决:https://blog.csdn.net/qq_16681169/article/details/75138876 缓存穿透 缓存穿透是指查询一个一定不存 ...

  6. redis缓存穿透,缓存击穿,缓存雪崩

    缓存穿透 缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有.这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询).这样请求就会绕过 ...

  7. 缓存穿透、雪崩、热点与Redis

    (拼多多问:Redis雪崩解决办法) 导读:互联网系统中不可避免要大量用到缓存,在缓存的使用过程中,架构师需要注意哪些问题?本文以 Redis 为例,详细探讨了最关键的 3 个问题. 一.缓存穿透预防 ...

  8. 什么是redis缓存穿透, 缓存雪崩, 缓存击穿

    什么是redis? redis是一个非关系型数据库,相对于其他数据库而言,它的查询速度极快,且能承受的瞬时并发量非常的高.所以常常被用来存放网站的缓存,以减少主要数据库(如mysql)的服务器压力. ...

  9. Redis系列(八)--缓存穿透、雪崩、更新策略

    1.缓存更新策略 1.LRU/LFU/FIFO算法剔除:例如maxmemory-policy 2.超时剔除,过期时间expire,对于一些用户可以容忍延时更新的数据,例如文章简介内容改了几个字 3.主 ...

  10. 缓存穿透 & 缓存雪崩 & 缓存击穿

    一 缓存穿透 1. 行为 查询一个一定不存在的数据.存储层(姑且认为是db,下面都用db指代)查不到数据则不写入缓存,那么下次请求这个不存在的数据同样会到db层查询,失去了缓存的意义.流量大或人为恶意 ...

随机推荐

  1. SpringBoot中bean的生命周期

    目录 概述 使用场景 代码演示bean初始化 TestSupport BeanPostProcessorImpl log 代码 概述 Bean 生命周期管理是 Spring Boot 中的关键功能之一 ...

  2. Java 日期和时间 API:实用技巧与示例 - 轻松处理日期和时间

    Java 用户输入(Scanner) 简介 Scanner 类用于获取用户输入,它位于 java.util 包中. 使用 Scanner 类 要使用 Scanner 类,请执行以下步骤: 导入 jav ...

  3. 遵循这些MySQL设计规范,再也没被组长喷过

    分享是最有效的学习方式. 博客:https://blog.ktdaddy.com/ 故事 会议室里,小猫挠着头,心里暗暗叫苦着"哎,这代码都撸完了呀,改起来成本也太大了." 原来就 ...

  4. Python设计模式----4.构建者模式

    构建者模式: 将一个复杂对象的构造与表现进行分离,利用多个步骤进行创建,同一个构建过程可用于创建多个不同的表现 构建者模式一般由 Director(指挥官)和 Builder(建设者)构成 class ...

  5. 润乾报表与 ActiveReport JS 功能对比

    简介 润乾报表是用于报表制作的大型企业级报表软件,核心特点在于开创性地提出了非线性报表数学模型,采用了革命性的多源关联分片.不规则分组.自由格间运算.行列对称等技术,使得复杂报表的设计简单化,以往难以 ...

  6. CF1933D Turtle Tenacity: Continual Mods

    思路: 此题其实很简单,不要被邪恶的出题人迷惑了双眼. 此题判断有解一共有两种情况. 通过题意可以知道将原数组排序后如果 \(b_{1} \ne b_{2}\),那么最后的结果一定 \(\ne 0\) ...

  7. c#程序员必学清单补充

    作为 C# 程序员,除了上述经典书籍和开源框架外,还需要掌握以下技术: 1. .NET Core 和 ASP.NET Core:了解并熟练掌握 .NET Core 和 ASP.NET Core 框架, ...

  8. 力扣1(java&python)-两数之和(简单)

    题目: 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标. 你可以假设每种输入只会对应一个答案.但是, ...

  9. 力扣165(java)-比较版本号(中等)

    题目: 给你两个版本号 version1 和 version2 ,请你比较它们. 版本号由一个或多个修订号组成,各修订号由一个 '.' 连接.每个修订号由 多位数字 组成,可能包含 前导零 .每个版本 ...

  10. OceanBase初体验之Docker快速部署试用环境

    前置条件 准备好一台安装了 Docker 的 Linux 服务器,确保能够连接到 Docker Hub 仓库. 执行以下命令拉取最新的 OceanBase 镜像: docker pull oceanb ...