美团面试拷打:Redis 缓存穿透、缓存击穿、缓存雪崩区别和解决方案

news2025/1/14 18:01:21

目录

图片

缓存穿透

什么是缓存穿透?

缓存穿透说简单点就是大量请求的 key 是不合理的,根本不存在于缓存中,也不存在于数据库中 。这就导致这些请求直接到了数据库上,根本没有经过缓存这一层,对数据库造成了巨大的压力,可能直接就被这么多请求弄宕机了。

图片

缓存穿透

举个例子:某个黑客故意制造一些非法的 key 发起大量请求,导致大量请求落到数据库,结果数据库上也没有查到对应的数据。也就是说这些请求最终都落到了数据库上,对数据库造成了巨大的压力。

有哪些解决办法?

最基本的就是首先做好参数校验,一些不合法的参数请求直接抛出异常信息返回给客户端。比如查询的数据库 id 不能小于 0、传入的邮箱格式不对的时候直接返回错误消息给客户端等等。

1)缓存无效 key

如果缓存和数据库都查不到某个 key 的数据就写一个到 Redis 中去并设置过期时间,具体命令如下:SET key value EX 10086 。这种方式可以解决请求的 key 变化不频繁的情况,如果黑客恶意攻击,每次构建不同的请求 key,会导致 Redis 中缓存大量无效的 key 。很明显,这种方案并不能从根本上解决此问题。如果非要用这种方式来解决穿透问题的话,尽量将无效的 key 的过期时间设置短一点比如 1 分钟。

另外,这里多说一嘴,一般情况下我们是这样设计 key 的:表名:列名:主键名:主键值 。

如果用 Java 代码展示的话,差不多是下面这样的:

public Object getObjectInclNullById(Integer id) {
    // 从缓存中获取数据
    Object cacheValue = cache.get(id);
    // 缓存为空
    if (cacheValue == null) {
        // 从数据库中获取
        Object storageValue = storage.get(key);
        // 缓存空对象
        cache.set(key, storageValue);
        // 如果存储数据为空,需要设置一个过期时间(300秒)
        if (storageValue == null) {
            // 必须设置过期时间,否则有被攻击的风险
            cache.expire(key, 60 * 5);
        }
        return storageValue;
    }
    return cacheValue;
}

2)布隆过滤器

布隆过滤器是一个非常神奇的数据结构,通过它我们可以非常方便地判断一个给定数据是否存在于海量数据中。我们可以把它看作由二进制向量(或者说位数组)和一系列随机映射函数(哈希函数)两部分组成的数据结构。相比于我们平时常用的 List、Map、Set 等数据结构,它占用空间更少并且效率更高,但是缺点是其返回的结果是概率性的,而不是非常准确的。理论情况下添加到集合中的元素越多,误报的可能性就越大。并且,存放在布隆过滤器的数据不容易删除。

图片

Bloom Filter 的简单原理示意图

Bloom Filter 会使用一个较大的 bit 数组来保存所有的数据,数组中的每个元素都只占用 1 bit ,并且每个元素只能是 0 或者 1(代表 false 或者 true),这也是 Bloom Filter 节省内存的核心所在。这样来算的话,申请一个 100w 个元素的位数组只占用 1000000Bit / 8 = 125000 Byte = 125000/1024 KB ≈ 122KB 的空间。

图片

位数组

具体是这样做的:把所有可能存在的请求的值都存放在布隆过滤器中,当用户请求过来,先判断用户发来的请求的值是否存在于布隆过滤器中。不存在的话,直接返回请求参数错误信息给客户端,存在的话才会走下面的流程。

加入布隆过滤器之后的缓存处理流程图如下。

图片

加入布隆过滤器之后的缓存处理流程图

更多关于布隆过滤器的详细介绍可以看看我的这篇原创:布隆过滤器有什么用?什么原理?如何使用?,强烈推荐。

3)接口限流

根据用户或者 IP 对接口进行限流,对于异常频繁的访问行为,还可以采取黑名单机制,例如将异常 IP 列入黑名单。

缓存击穿

什么是缓存击穿?

缓存击穿中,请求的 key 对应的是 热点数据 ,该数据 存在于数据库中,但不存在于缓存中(通常是因为缓存中的那份数据已经过期) 。这就可能会导致瞬时大量的请求直接打到了数据库上,对数据库造成了巨大的压力,可能直接就被这么多请求弄宕机了。

图片

缓存击穿

举个例子:秒杀进行过程中,缓存中的某个秒杀商品的数据突然过期,这就导致瞬时大量对该商品的请求直接落到数据库上,对数据库造成了巨大的压力。

有哪些解决办法?
  1. 设置热点数据永不过期或者过期时间比较长。

  2. 针对热点数据提前预热,将其存入缓存中并设置合理的过期时间比如秒杀场景下的数据在秒杀结束之前不过期。

  3. 请求数据库写数据到缓存之前,先获取互斥锁,保证只有一个请求会落到数据库上,减少数据库的压力。

缓存穿透和缓存击穿有什么区别?

缓存穿透中,请求的 key 既不存在于缓存中,也不存在于数据库中。

缓存击穿中,请求的 key 对应的是 热点数据 ,该数据 存在于数据库中,但不存在于缓存中(通常是因为缓存中的那份数据已经过期) 。

缓存雪崩

什么是缓存雪崩?

我发现缓存雪崩这名字起的有点意思,哈哈。

实际上,缓存雪崩描述的就是这样一个简单的场景:缓存在同一时间大面积的失效,导致大量的请求都直接落到了数据库上,对数据库造成了巨大的压力。 这就好比雪崩一样,摧枯拉朽之势,数据库的压力可想而知,可能直接就被这么多请求弄宕机了。

另外,缓存服务宕机也会导致缓存雪崩现象,导致所有的请求都落到了数据库上。

图片

缓存雪崩

举个例子:数据库中的大量数据在同一时间过期,这个时候突然有大量的请求需要访问这些过期的数据。这就导致大量的请求直接落到数据库上,对数据库造成了巨大的压力。

有哪些解决办法?

针对 Redis 服务不可用的情况:

  1. 采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。

  2. 限流,避免同时处理大量的请求。

  3. 多级缓存,例如本地缓存+Redis 缓存的组合,当 Redis 缓存出现问题时,还可以从本地缓存中获取到部分数据。

针对热点缓存失效的情况:

  1. 设置不同的失效时间比如随机设置缓存的失效时间。

  2. 缓存永不失效(不太推荐,实用性太差)。

  3. 缓存预热,也就是在程序启动后或运行过程中,主动将热点数据加载到缓存中。

缓存预热如何实现?

常见的缓存预热方式有两种:

  1. 使用定时任务,比如 xxl-job,来定时触发缓存预热的逻辑,将数据库中的热点数据查询出来并存入缓存中。

  2. 使用消息队列,比如 Kafka,来异步地进行缓存预热,将数据库中的热点数据的主键或者 ID 发送到消息队列中,然后由缓存服务消费消息队列中的数据,根据主键或者 ID 查询数据库并更新缓存。

缓存雪崩和缓存击穿有什么区别?

缓存雪崩和缓存击穿比较像,但缓存雪崩导致的原因是缓存中的大量或者所有数据失效,缓存击穿导致的原因主要是某个热点数据不存在与缓存中(通常是因为缓存中的那份数据已经过期)。

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

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

相关文章

okHttp MediaType MIME格式详解

一、介绍 我们在做数据上传时,经常会用到Okhttp的开源库,okhttp开源库也遵循html提交的MIME数据格式。 所以我们经常会看到applicaiton/json这样的格式在传。 但是如果涉及到其他文件等就需要详细的数据格式,否则服务端无法解析 二、okHt…

滞销番茄变废为宝,成功打造市场份额第一番茄品牌|日本极致产品力

可果美是日本市场领先的番茄品牌,然而在可果美发展初期,番茄只是供应链中的滞销产品。可果美通过极致产品力的打造,将番茄“变废为宝”,打败亨氏、味好美成为可果美的招牌。可果美是如何做到的呢? 番茄是可果美供应链的滞销品 在…

MCU中断里使用软延时函数delay_ms(u16 x)问题及实例探讨

原贴有误已删:https://blog.csdn.net/weixin_50007421/article/details/136138221 今天完善如下: 本意:只是想表达“复杂系统中断里当然尽量不用软延时函数,但简单系统只要心中有数逻辑清楚实测无妨就完全可行”。 但后来感觉还…

Linux基础命令[11]-find

文章目录 1. find 命令说明2. find 命令语法3. find 命令示例3.1 不加参数3.2 按照时间3.3 -empty(空白文件或目录)3.4 -name(名称查找)3.5 -size(大小查找)3.6 -type(类型查找)3.7 …

【中间件】docker的安装

📝个人主页:五敷有你 🔥系列专栏:中间件 ⛺️稳中求进,晒太阳 .卸载旧版 首先如果系统中已经存在旧的Docker,则先卸载: yum remove docker \docker-client \docker-client-latest \doc…

数据结构:顺序表的奥秘

🎉个人名片: 🐼作者简介:一名乐于分享在学习道路上收获的大二在校生🐻‍❄个人主页🎉:GOTXX 🐼个人WeChat:ILXOXVJE🐼本文由GOTXX原创,首发CSDN&a…

数据库设计说明书-word

2 数据库环境说明 3 数据库的命名规则 4 逻辑设计 5 物理设计 5.1 表汇总 5.2 表结构设计 6 数据规划 6.1 表空间设计 6.2 数据文件设计 6.3 表、索引分区设计 6.4 优化方法 7 安全性设计 7.1 防止用户直接操作数据库 7.2 用户帐号加密处理 7.3 角色与权限控制 8 数据库管理与维…

高级控件

1.下拉列表 package com.tiger.chapter08;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Spinner;public class Spi…

短视频矩阵系统----矩阵系统源码搭建(技术门槛?)

短视频矩阵是什么意思?短视频矩阵的含义可以理解为全方位的短视频账号,通过不同的账号实现全方位的品牌展示。实际上是指一个短视频账号,通过不同的链接实现品牌展示,在不同的粉丝流量账号中互相转发同一个品牌,在主账…

SemanticKITTI点云地图拼接 SemanticKITTI语义地图

自己用点云分割的预测结果,和里程计的结果拼接出整个轨迹,某种程度上也算是语义语义地图 只需要pcl c就可以,参了以下博主 kitti点云地图拼接_kitti点云拼接-CSDN博客 SemanticKITTI点云拼接PCL可视化_可视化semantickitti .bin-CSDN博客 …

《人工智能怎么学》荣获2023年吴文俊人工智能科学技术奖及赠书活动

中国人工智能学会官网(www.caai.cn)近日正式公布了2023年吴文俊科学技术奖获奖名单,图书《人工智能怎么学》项目被授予2023年吴文俊人工智能科学技术奖科技进步奖(科普项目)。2023年吴文俊科学技术奖完整获奖名单见htt…

实现大华摄像头的抓图-使用HTTP方式

实现抓图,网上大部分都是使用SDK二次开发的,HTTP接口实现的基本没有介绍,好像官方叫CUI接口,但是找官方要文档,基本要不到,我自己下载了一份以前的文档,可以做大部分操作,这里免费分…

基于MPPT的太阳能光伏电池simulink性能仿真,对比扰动观察法,增量电导法,恒定电压法

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 扰动观察法 (Perturb and Observe Method) 4.2 增量电导法 (Incremental Conductance Method) 4.3 恒定电压法 (Constant Voltage Method) 5.完整工程文件 1.课题概述 在simulink中,实…

RNN实现退位减法

文章目录 前言RNNRNN架构图前向传播公式反向传播算法 用RNN实现退位减法代码变量的对应关系 总结 前言 最近深入学习了一下RNN,即循环神经网络。RNN是一类比较基础的神经网络,本文使用的是最基础、最简单的循环神经网络的形式。LSTM也是一种常见的循环神…

中大型工厂人员定位系统源码,实现人、车、物的实时位置监控

UWB高精度定位系统源码,中大型工厂人员定位系统,实现人、车、物的实时位置监控 UWB高精度定位系统源码,智慧工厂人员定位系统源码,基于VueSpring boot前后端分离架构开发的一套UWB高精度定位系统源码。有演示。 随着经济的高速发展…

Flink实时数仓同步:切片表实战详解

一、背景 在大数据领域,初始阶段业务数据通常被存储于关系型数据库,如MySQL。然而,为满足日常分析和报表等需求,大数据平台采用多种同步方式,以适应这些业务数据的不同存储需求。 一项常见需求是,业务使用…

潜水耳机哪个牌子好?认准这几个游泳耳机品牌就对了!

在科技日益发达的今天,人们对于运动设备的需求也在不断提升。作为一项独特的水上运动,潜水爱好者们对耳机的要求也越来越高。一款优秀的潜水耳机不仅能够提供卓越的防水性能和舒适度,还必须具备出色的音质。那么,在众多品牌中&…

C语言进阶—表达式求值

隐式类型转换&#xff1a; C 的整型算术运算总是至少以缺省(默认)整型类型的精度来进行的。 为了获得这个精度&#xff0c;表达式中的字符和短整型操作数在使用之前被转换为普通整型&#xff0c;这种转换称为整型提升。 #include <stdio.h>int main() {char c 1;printf(…

鸿蒙Harmony应用开发—ArkTS声明式开发(自定义手势判定)

为组件提供自定义手势判定能力。开发者可根据需要&#xff0c;在手势识别期间&#xff0c;决定是否响应手势。 说明&#xff1a; 从API Version 11开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 onGestureJudgeBegin onGestureJudgeBegi…

C#与python交互(flask发送Get/Post请求)

先运行python&#xff0c;再运行C# **ps: 注意修改端口号**python发送Get/Post请求 # -*- coding: utf-8 -*- # Time : 2024/1/25 15:52 # Author : YY # File : post_test.py # Content&#xff1a;提交数据给客户端 from flask import Flask, request, jsonify, redirect…