大厂面试官问我:Redis缓存如果扛不住,该怎么办?【后端八股文十一:Redis缓存八股文合集(1)】

 本文为【Redis分布式锁八股文合集(2)】初版,后续还会进行优化更新,欢迎大家关注交流~

hello hello~ ,这里是绝命Coding——老白~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹
19d95742d45b4220ad0ae0359ffcba93.png

💥个人主页:绝命Coding-CSDN博客
💥 所属专栏:后端技术分享
这里将会不定期更新有关后端、前端的内容,希望大家多多点赞关注收藏💖

    往期内容(篇幅过多,不一一列出,感兴趣的小伙伴可以查看专栏):

大厂面试官问我:Redis处理点赞,如果瞬时涌入大量用户点赞(千万级),应当如何进行处理?【后端八股文一:Redis点赞八股文合集】-CSDN博客

大厂面试官问我:布隆过滤器有不能扩容和删除的缺陷,有没有可以替代的数据结构呢?【后端八股文二:布隆过滤器八股文合集】-CSDN博客

大厂面试官问我:Redis持久化RDB有没有可能阻塞?阻塞点在哪里?【后端八股文三:Redis持久化八股文合集】-CSDN博客

Redis缓存

为什么Redis做缓存?

(高并发,高性能——内存)
(1)高并发
承受的请求  大  ( 直接缓存   数据库)
(单台设备的 Redis 的 QPS(每秒处理完请求的次数)是Mysql的10倍,Redis 单机的 QPS 能轻松破 10w,而 MySQL 单机的 QPS 很难破 1w)
(2)高性能
第一次访问,从硬盘;
缓存,直接内存,速度快

redis作为缓存的使用场景?/ 哪些数据适合放入缓存

即时性、数据线要求不高
访问量大且更新频率不高的数据(读多,写少)

比如:电商商品

什么是缓存预热

缓存预热是指系统上线后,提前将相关的缓存数据加载到缓存系统。避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题,用户直接查询事先被预热的缓存数据。

如果不进行预热,那么Redis初始状态数据为空,系统上线初期,对于高并发的流量,都会访问到数据库中, 对数据库造成流量的压力。

缓存预热解决方案:

数据量不大的时候,工程启动的时候进行加载缓存动作;

数据量大的时候,设置一个定时任务脚本,进行缓存的刷新;

数据量太大的时候,优先保证热点数据进行提前加载到缓存。

假设一种高热的数据它突然之间过期了,怎么预防这样的情况?你就那比如说恰好这一秒钟我过期了,正好这一秒钟有一两万个QPS

  1. 分布式缓存: 考虑使用分布式缓存方案,如Redis集群,将热数据分散存储在多个节点上,减少单一节点的过期负担。
  2. 过期时间随机化: 在设置过期时间时,可以引入一些随机化因素,以减少在相同时刻过期的可能性。
  3. 限制过期数据量: 设置过期数据的限制,确保在同一时刻过期的数据数量有一个上限,从而避免过多的数据一起过期。
  4. 增加缓存节点: 如果预计在某个时间段内会有大量数据过期,可以临时增加缓存节点数量,以扩展缓存容量和处理能力。
  5. 过期前刷新: 对于热数据,可以在过期之前进行刷新,延长数据的有效期。这样可以避免数据突然过期造成的负载冲击。
  6. 流量控制: 在高并发情况下,可以实施流量控制机制,限制同时访问过期数据的请求数量,减轻过期时的压力。
  7. 淘汰策略: 使用合适的淘汰策略,如LRU(最近最少使用)等,使得热数据能够保持在缓存中,减少过期的影响。

缓存雪崩,缓存穿透,缓存击穿 / 常见问题解决方案

(缓存穿透——不存在、缓存击穿——访问量大、缓存雪崩——过期时间)

缓存雪崩
指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。

解决:
缓存数据的过期时间设置随机(防止同一时间大量数据过期现象发生)
加锁排队:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个 key 只允许一个线程查询数据和写缓存,其他线程等待;
数据预热:可以通过缓存 reload 机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存不同的 key,设置不同的过期时间,让缓存失效的时间点尽量均匀;

  1. 均匀设置过期时间:设置不同的过期时间,让缓存失效的时间点尽量均匀。通常可以为有效期增加随机值
  2. 互斥锁:同一时间只让一个线程构建缓存,其他线程阻塞排队。
  3. 双 key 策略:
    主缓存:有效期按照经验值设置,设置为主读取的缓存,主缓存失效后从数据库加载最新值
    备份缓存:有效期长获取锁失败时读取的缓存主缓存更新时需要同步更新备份缓存
    (限流、提前缓存)

缓存击穿
一份热点数据访问量过大,在缓存失效,请求直达存储层     服务器崩溃
(可以发现缓存击穿跟缓存雪崩很相似,你可以认为缓存击穿是缓存雪崩的一个子集。)
解决:
永不过期,不给热点数据设置过期时间
加互斥锁

缓存穿透
客户端查询不存在的数据     请求直达存储层    负载过大(既不在缓存中,也不在数据库中
原因:业务层误将缓存和库中数据删除
有人恶意访问库中不存在的
解决:
缓存空对象,并加入短暂过期时间(存储层未命中,仍将空值缓存)
布隆过滤器(数据存入过滤器,访问缓存前拦截,若请求数据不存在则返回空值)
非法请求的限制

缓存击穿的互斥锁怎么实现的?

使用setnx作为Redis中的锁。

Redis中查询缓存

  • 存在且不为空值,直接返回
  • 为空值(比如“”、0等特殊值),返回失败结果
  • 不存在,获取锁

获取锁失败,等待重试

获取成功,查找MySQL

  • 不存在,Redis存入空值
  • 存在,写入Redis

释放锁,返回结果

public Result queryShopById(Long id) {// 用String形式存储JSONString shopJson = stringRedisTemplate.opsForValue().get(CACHE_SHOP_KEY + id);// 如果查询结果不为null,直接返回if (StrUtil.isNotBlank(shopJson)) {Shop shop = JSONUtil.toBean(shopJson, Shop.class);return Result.ok(shop);}// 否则Redis中查询结果为空,判断是否为“”if (shopJson != null) {return Result.fail("店铺不存在,请确认id是否正确");}// 尝试获取锁,// 如果没有得到锁,Sleep一段时间if (!tryLock(LOCK_SHOP_KEY + id)) {try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}// 从开始重试return queryShopById(id);}// 获得了锁,从MySQl中查找Shop shop = this.getById(id);// 模拟重建的延时try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}// 不在MySQL中if (shop == null) {// 将空值写入RedisstringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, "", CACHE_NULL_TTL, TimeUnit.MINUTES);// 释放锁unLock(LOCK_SHOP_KEY + id);return Result.fail("店铺不存在,请确认id是否正确");}else {// 在MySQL中,存入redisstringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);// 释放锁unLock(LOCK_SHOP_KEY + id);return Result.ok(shop);}
}public boolean tryLock(String key) {// 尝试获取锁,set成功返回true,否则返回falseBoolean getLock = stringRedisTemplate.opsForValue().setIfAbsent(key, "1", 10, TimeUnit.SECONDS);// 避免getLock为null,使用工具类return BooleanUtil.isTrue(getLock);
}public void unLock(String key) {stringRedisTemplate.delete(key);
}

一般我们在更新数据库数据时,需要同步redis中缓存的数据,所以存在两种方法:
第一种方案:先执行update操作,再执行缓存清除。
第二种方案:先执行缓存清除,再执行update操作。
这两种方案的弊端是当存在并发请求时,很容易出现以下问题:
第一种方案:当请求1执行update操作后,还未来得及进行缓存清除,此时请求2查询到并使用了redis中的旧数据。
第二种方案:当请求1执行清除缓存后,还未进行update操作,此时请求2进行查询到了旧数据并写入了redis。

所以此时我们需要使用第三种方案:先进行缓存清除,再执行update,最后(延迟N秒)再执行缓存清除。

上述中(延迟N秒)的时间要大于一次写操作的时间,一般为3-5秒。
        原因:如果延迟时间小于写入redis的时间,会导致请求1清除了缓存,但是请求2缓存还未写入的尴尬。。。
        ps:一般写入的时间会远小于5秒

先更新db再删缓存,如果删失败了怎么办?

事务,回退数据库
延迟删除

如果Redis缓存扛不住怎么办?

使用本地缓存(在面对大部分并发场景或者一些中小型公司流量没有那么高的情况,使用redis基本都能解决了。但是在流量较高的情况下可能得使用到本地缓存了)
比如guava的LoadingCache和快手开源的ReloadableCache。

如果单节点qps达到了千级别就要解决单点问题了(即使redis号称能抗住十万级别的qps)

本地缓存

在一些场景下可能单纯使用Redis类的远程缓存已经不够了,还需要进一步配合本地缓存使用,例如Guava cache或Caffeine,从而再次提升程序的响应速度与服务性能。于是,就产生了使用本地缓存作为一级缓存,再加上远程缓存作为二级缓存的两级缓存架构。

为什么要使用本地缓存
  • 本地缓存基于本地环境的内存,访问速度非常快,对于一些变更频率低、实时性要求低的数据,可以放在本地缓存中,提升访问速度
  • 使用本地缓存能够减少和Redis类的远程缓存间的数据交互,减少网络I/O开销,降低这一过程中在网络通信上的耗时

本地缓存问题及解决
1. 缓存一致性

两级缓存与数据库的数据要保持一致,一旦数据发生了修改,在修改数据库的同时,本地缓存、远程缓存应该同步更新。
解决方案1: MQ

一般现在部署都是集群部署,有多个不同节点的本地缓存; 可以使用MQ的广播模式,当数据修改时向MQ发送消息,节点监听并消费消息,删除本地缓存,达到最终一致性;

解决方案2:Canal + MQ

如果你不想在你的业务代码发送MQ消息,还可以适用近几年比较流行的方法:订阅数据库变更日志,再操作缓存。Canal 订阅Mysql的 Binlog日志,当发生变化时向MQ发送消息,进而也实现数据一致性。

redis优化缓存结构

(1)使用Redis和Cache 多级缓存;

(2)Caffine+Redis+ES 做三级缓存;

(3)使用 Redis 实现分布式缓存,另外配合 Nginx 缓存 + 本地 Caffeine 缓存 + CDN 缓存 + 浏览器缓存共同实现多级缓存来保证系统的性能。

(4)使用mq转发(来自京东技术:营销权益平台春晚技术探究):

本地缓存的构建的两种方式:

  • 一级缓存:本地+mysql+推模式更新。
  • 两级缓存:本地+r2m+mysql+推模式更新。

     后期新的八股文合集文章会继续分享,感兴趣的小伙伴可以点个关注~

 更多精彩内容以及免费资料请关注公众号:绝命Coding

914cbb12b2c3492aaa31232a11aa9c64.png

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

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

相关文章

C++ | Leetcode C++题解之第22题完全二叉树的节点个数

题目&#xff1a; 题解&#xff1a; class Solution { public:int countNodes(TreeNode* root) {if (root nullptr) {return 0;}int level 0;TreeNode* node root;while (node->left ! nullptr) {level;node node->left;}int low 1 << level, high (1 <&…

三级_网络技术_08_IP地址规划技术

1.如果内网的某Web服务器允许外网访问&#xff0c;并且该服务器NAT转换表如图所示&#xff0c;那么外网主机正确访问该服务器时使用的URL是()。 http://59.12.1.1:1423 http://135.2.2.1 http://135.2.2.1:5511 http://192.168.33.11:80 2.如果内网的某FTP服务器允许外网访…

基于大数据技术Hadoop的气象分析可视化大屏设计和实现

博主介绍&#xff1a;硕士研究生&#xff0c;专注于信息化技术领域开发与管理&#xff0c;会使用java、标准c/c等开发语言&#xff0c;以及毕业项目实战✌ 从事基于java BS架构、CS架构、c/c 编程工作近16年&#xff0c;拥有近12年的管理工作经验&#xff0c;拥有较丰富的技术架…

网络资源模板--Android Studio 外卖点餐App

目录 一、项目演示 二、项目测试环境 三、项目详情 四、完整的项目源码 原创外卖点餐&#xff1a;基于Android studio 实现外卖(点)订餐系统 非原创奶茶点餐&#xff1a;网络资源模板--基于 Android Studio 实现的奶茶点餐App报告 一、项目演示 网络资源模板--基于Android …

vb.netcad二开自学笔记6:第一个绘制线段命令

.net编写绘制直线已完全不同于ActiveX的&#xff08;VBA&#xff09;的方式&#xff0c;过程更类似于arx程序&#xff0c;需要通过操作AutoCAD 数据库添加对象&#xff01;下面的代码是在以前代码基础上添加了一个新myline命令。 AutoCAD 数据库结构 myline命令代码 Imports A…

Unity AssetsBundle 详解

文章目录 1.AssetBundle 概念2.AssetBundle 优势3.AssetBundle 特性4.AssetBundle 使用流程4.1 分组4.2 打包4.3 加载包4.4 加载资源4.5 卸载资源 5.AssetBundleManifest6.AssetBundle的内存占用7.AB包资源加密 1.AssetBundle 概念 AssetBundle又称AB包&#xff0c;是Unity提供…

hadoop分布式中某个 节点报错的解决案例

前言 在分布式节点中&#xff0c;发现有个节点显示不可用状态&#xff0c;因此需要紧急修复。 hadoop版本 目前这套集群hadoop的版本如下&#xff1a; 集群报错详细日志&#xff1a; 1/1 local-dirs are bad: /kkb/install/hadoop-2.6.0-cdh5.14.2/hadoopDatas/tempDatas/n…

服务器本地部署文件服务器minio

minio类似于阿里云的OSS&#xff0c;为不方便把图、文、日志等形式的文件保存在公有云上的&#xff0c;可以在自己的服务器上部署文件服务器 看过本人前几个文章的&#xff0c;使用docker就会很快上手部署&#xff0c;直接上所有代码 #添加镜像 docker search minio docker p…

python - 文件 / 永久存储:pickle / 异常处理

一.文件 利用help(open)可以看到open()函数的定义&#xff1a; >>> help(open) Help on built-in function open in module _io:open(file, moder, buffering-1, encodingNone, errorsNone, newlineNone, closefdTrue, openerNone) 默认打开模式是’rt’&#xff0…

【网络安全】实验三(基于Windows部署CA)

一、配置环境 打开两台虚拟机&#xff0c;并参照下图&#xff0c;搭建网络拓扑环境&#xff0c;要求两台虚拟的IP地址要按照图中的标识进行设置&#xff0c;并根据搭建完成情况&#xff0c;勾选对应选项。注&#xff1a;此处的学号本人学号的最后两位数字&#xff0c;1学号100…

逆袭707计划

暑假沉淀计划707 上午&#xff1a; 早起习惯&#xff1a;先打开idea将昨日所学代码敲一遍&#xff08;预估半小时&#xff09; 早饭时间可并发查看是否有自媒体商单 学习一节JavaEE课程&#xff08;预估一个半小时&#xff09; 完成对应的作业&#xff08;预估一个小时&am…

Python28-9 XGBoost算法

XGBoost&#xff08;eXtreme Gradient Boosting&#xff0c;其正确拼写应该是 "Extreme Gradient Boosting"&#xff0c;而XGBoost 的作者在命名时故意使用了不规范的拼写&#xff0c;将“eXtreme”中的“X”大写&#xff0c;以突出其极限性能和效率&#xff09;是一…

【python学习】快速了解python基本数据类型

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 前言1. 整数&#xff08;int&#xff09;2. 浮点数&#xff08;float&#xff09;3. 布尔值&#xff08;bool&#xf…

WPS+Python爬取百度之星排名

运行效果 手动拉取 https://www.matiji.net/exam/contest/contestdetail/146 如果手动查找&#xff0c;那么只能通过翻页的方式&#xff0c;每页10行&#xff08;外加一行自己&#xff09;。 爬取效果预览 本脚本爬取了个人排名和高校排名&#xff0c;可以借助WPS或MS Offi…

前端web在线PPT编辑器-PPTLIST

哈喽&#xff0c;大家好&#xff0c;今天给大家介绍一款的在线的PPT编辑器开源框架-PPTLIST&#xff1b;他是一个基于 Vue3.x TypeScript 的在线演示文稿&#xff08;幻灯片&#xff09;应用&#xff0c;还原了大部分 Office PowerPoint 常用功能&#xff0c;支持 文字、图片、…

【ffmpeg系列一】源码构建,ubuntu22与win10下的过程对比。

文章目录 背景ubuntu22结论 win10过程 对比结论 背景 顺手编译个ffmpeg试试&#xff0c;看看不同平台下谁的配置比较繁琐。 先让gpt给出个教程&#xff1a; ubuntu22 使用elementary-os7.1构建&#xff0c;看看有几个坑要踩。 错误1&#xff1a; 依赖libavresample-dev未…

明日周刊-第15期

赶在周末结束前输出一把&#xff0c;周日的晚上大家要睡个好觉哦。 文章目录 一周热点资源分享言论歌曲推荐 一周热点 科技创新与基础设施建设 深中通道正式通车试运营 时间&#xff1a;6月30日 内容&#xff1a;国家重大工程深中通道正式通车试运营&#xff0c;标志着珠江口东…

数据列表组件-报表

当数据在后端接口查询到&#xff0c;需要在页面展示出来&#xff0c;如果项目有很多report &#xff0c;可以把列表做一个组件 效果如下&#xff1a; js代码&#xff1a; <!DOCTYPE html> <html> <head><meta charset"utf-8" /><title&g…

用Goaccess对Web及雷池WAF日志实现可视化分析

君衍. 一、项目环境介绍二、Goaccess1、Goaccess介绍2、存储方式3、配置选项4、自定义日志/日期格式5、特殊格式说明符 三、雷池访问日志1、配置文件改变2、docker配置3、示例测试 四、Goaccess安装1、安装依赖2、编译安装 五、Goaccess对Nginx日志分析1、常用命令参数2、终端模…