基于Redis设计一个高可用的缓存

本文为您介绍,如何逐步设计一个基于Redis的高可用缓存。

目录

业务背景

步骤一:写一个最简单的缓存设计

存在的问题:大量冷数据占据Redis内存

解决思路:让缓存自主释放

步骤二:为缓存设置超时时间

存在的问题:热点缓存也会失效

解决思路:为热点缓存续命

步骤三:数据查询缓存后,重新设置缓存过期时间,为其续命

存在的问题:缓存击穿/缓存失效

解决思路:如何保证缓存不同一时间失效

步骤四:为缓存设置不一样的失效时间​编辑

存在的问题:缓存穿透

解决思路:拦截查询不存在数据请求,禁止直击数据库

步骤五:为不存在的数据创建空缓存并为其指定过期时间,并对重复请求的空缓存续命​编辑

存在的问题:冷数据突变热数据,导致众多获取冷数据的请求直接打在了数据库

解决思路:只让一个查询冷数据的请求查询数据库并为其创建缓存,其他请求查缓存

总结:上述锁已经能解决99%的问题,但是还存在一定缺陷

业务背景

本文将以如何查询,更改个商品的为例,讲述高并发下,如何设计一个高并发缓存。

步骤一:写一个最简单的缓存设计

以下代码是常见的最简单的redis缓存的设计:

  • 新增、更改数据时,更新缓存。
  • 查询时,先查询缓存。
    • 缓存存在,直接返回。
    • 缓存不存在,查询数据库,且更新缓存数据。

存在的问题:大量冷数据占据Redis内存

在数据少,压力小,并发小的情况下,这个设计似乎没有什么大问题,但是在数据量大,高并发的情况下,却会有不少问题。
例如系统有上亿数据,但是用户经常访问的数据,只有几百万数据,那么大量冷数据常驻Redis内存,造成redis内存浪费。

解决思路:让缓存自主释放

既然这个数据在一段时间内无人问津,那么是不是可以根据一定规则,让缓存自主失效就可以了?那么为缓存设计一个失效时间就可以了?

步骤二:为缓存设置超时时间

存在的问题:热点缓存也会失效

在为缓存设置超时时间后,那么热点数据的缓存,在该设置的时间内,也会失效,那么缓存失效后,大量请求查询无缓存后,都会请求到数据库,这样会造成数据库的压力增大。

解决思路:为热点缓存续命

如何在缓存设置了失效时间后,只是让冷数据失效,热数据不失效呢?此时您有没有想到为热点数据的缓存续命的方法吗?那就每次请求查询缓存后,为该缓存重新设置缓存失效时间,延长其失效时间,这样是不是就为其续命了呢?

步骤三:数据查询缓存后,重新设置缓存过期时间,为其续命

存在的问题:缓存击穿/缓存失效

上述方案中,如果您批量导入数据或者批量新增数据,那么这些数据建立缓存时缓存失效的时间会差不多一样,那么就会出现大批量缓存在同一时间失效可能导致大量请求同时穿透缓存直达数据库,可能会造成数据库瞬间压力过大甚至挂掉。

解决思路:如何保证缓存不同一时间失效

上述方案中,大量请求直击数据库的主要原因是因为缓存失效的时间也是同一时间,那么如何让缓存失效时间不一样呢?在设置缓存失效时,给设置不一样的时间是不是就可以了?例如在设计缓存时在设定时间上再加上一个随机时间。

步骤四:为缓存设置不一样的失效时间

存在的问题:缓存穿透

写到这里,您是不是觉得,这下没有问题了吧?还有一下小概率时间还未考虑到呢,比如缓存穿透的问题。
缓存穿透:

  • 是指查询一个根本不存在的数据,缓存层和存储层都不会命中。
  • 缓存穿透将导致不存在的数据每次请求都要到存储层去查询, 失去了缓存保护后端存储的意义。

造成缓存穿透的基本原因:

  • 自身业务代码或者数据出现问题。
  • 一些恶意攻击、 爬虫等造成大量空命中。

解决思路:拦截查询不存在数据请求,禁止直击数据库

怎么拦截这些查询不存在数据的请求呢?究其根本原因是,请求第一次查询缓存时,缓存没有,又继续查询数据库,数据库没有的就直接返回了。同样的请求会重复这样的动作。

想一下如何能拦截除第一次以外这样的请求呢?那可不可以在第一次这样的请求后,在其查询数据库也没有的后,仍然为其创建一个空缓存,这样其他请求是不是就会被拦截到缓存层,就不会直击数据库了呢?

只是为其创建一个空缓存就够了吗?那么恶意攻击后,这样Redis中是不是还会存在这种大量的空缓存,浪费Redis 内存呢? 同样的,还需为其加一个过期时间。

那么如果对同一个不存在的数据恶意请求呢?那是不是还需要为其对应的空缓存续命呢?

步骤五:为不存在的数据创建空缓存并为其指定过期时间,并对重复请求的空缓存续命

存在的问题:冷数据突变热数据,导致众多获取冷数据的请求直接打在了数据库

比如大V直播间对冷产品的推广,导致大量用户同一时间抢购同一冷商品(缓存已经过期),导致大量请求直达数据库,造成数据库压力突然暴增。

解决思路:只让一个查询冷数据的请求查询数据库并为其创建缓存,其他请求查缓存

如何让众多请求中的一个查询查询数据库,并创建缓存,而其他请求查询该请求创建后的缓存呢?这听起来是不是有一个顺序的含义?谈到顺序,您是否想到锁机制呢?是的,这种场景,可以使用一把锁,解决该问题,思路如下:

当多个请求过来时,查询缓存没有数据时,要去查数据库前,获取一把锁,这样就能保证有一个请求该数据后,这个数据就存在了缓存中。

在获取锁后,再查询一次缓存,保证其他请求,获取锁后,直接查缓存,然后直接返回。

总结:上述锁已经能解决99%的问题,但是还存在一定缺陷

虽然上述锁已经解决了大多数问题,但还是有一些小概率问题会出现,例如以下问题:

  • 缓存与数据库双写不一致问题。
    例如线程A查询缓存为空,然后去读数据库,在读完数据库后,准备写缓存时,系统卡顿了,就在这期间,有一个线程B将数据做了更改,但待系统恢复后,线程A继续执行写入缓存的操作,但此时数据库中的内容已经是线程B更改过的数据了。
  • 热点数据突然暴增导致系统奔溃问题。
    热点数据突然访问过大,同一时刻又几十万、上百万的请求过来,Redis单节点也就能扛10万的并发,这种超大压力,都可能打垮Redis,导致系统崩溃。
  • 缓存雪崩问题。
    缓存雪崩指的是缓存层由于某些原因不能提供服务,导致大量请求都会打到存储层, 存储层的调用量会暴增, 最终造成存储层也会级联宕机的情况。

根据前面分析解决每个缓存设计出现问题的思路,针对这三个问题,您是否有解决思路呢?如果没有,您可参见https://blog.csdn.net/weixin_43134177/article/details/134151930,为您提供一定解决方案。

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

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

相关文章

从原理到实践:LVS+Keepalived构建高可用负载均衡集群

从原理到实践:LVSKeepalived构建高可用负载均衡集群 文章目录从原理到实践:LVSKeepalived构建高可用负载均衡集群一、为什么需要LVSKeepalived?二、核心原理:Keepalived与VRRP协议1. VRRP的核心思想2. Keepalived的三大功能三、LV…

iOS混淆工具实战 在线教育直播类 App 的课程与互动安全防护

近年来,在线教育直播类 App 已成为学生与培训机构的重要工具。无论是 K12 教育、职业培训,还是兴趣学习,App 中承载的课程视频、题库与互动逻辑都是极高价值的内容资产。 然而,教育直播应用同样面临多重安全风险:课程视…

第2节-过滤表中的行-BETWEEN

摘要: 在本教程中,您将学习如何在 WHERE 子句中使用 PostgreSQL 的 BETWEEN 运算符来检查某个值是否在两个值之间。 PostgreSQL BETWEEN 运算符 BETWEEN运算符是一种比较运算符,如果某个值介于两个值之间,则返回true。 以下是 BETWEEN 运算符…

Windows 11 手动下载安装配置 uv、配置国内源

Windows 11 手动下载安装配置 uv、配置国内源 本文对应的讲解视频链接:https://www.bilibili.com/video/BV1WnYTzZEpW 文章目录Windows 11 手动下载安装配置 uv、配置国内源1. 下载、安装、配置 uv2. 参考信息重要声明: uv 的安装有很多种方式&#xff…

平板热点频繁断连?三步彻底解决

平板反复断开热点连接是一个非常常见且令人烦恼的问题。这通常不是单一原因造成的,而是多种因素叠加的结果。 我们可以从热点发射设备(手机等)、平板本身、以及环境因素三个方面来排查和解决。 一、 热点发射端(通常是手机&#x…

Qt文件操作的学习(三)

一、实现简易文本编辑器 主要用到带菜单栏的窗口,而非单一窗口。QT已经写好相关操作,就不在重新造轮子了功能设计:新建文本文档,打开文件,保存文件,另存为 这次不同于之前直接可以在控件上面右击槽了&…

ArcGIS学习-20 实战-县域水文分析

水文分析任务提取区域内水流方向、汇流累积量、河网、流域、子流域前置操作环境更改加载数据检查投影坐标系河网分析洼地填充限制默认为空,认为所有洼地都是需要填充的,这里更正一下Fill_DEM需要加上后缀.tif流向分析得到流量分析得到这里的黑色代表非河…

本地 Docker 环境 Solr 配置 SSL 证书

一、简介 在本地开发环境中为 Solr 配置 SSL 证书,是提升开发与测试一致性的关键步骤。尤其是在涉及安全传输需求的场景中,本地环境的 HTTPS 配置能有效避免因环境差异导致的问题。本文将详细介绍如何利用 Docker 容器,快速为 Solr 服务配置自签名 SSL 证书,实现本地 HTTP…

MacOS 运行CosyVoice

CosyVoic主要特点:1、支持中文、英文、上海话、天津话、四川话等方言。语音非常自然。2、支持3秒语音零样本克隆,效果非常好。3、克隆时间比较长(取决于GPU性能,使用H20以满足低延迟输出),L4 克隆默认文本需…

我不是挂王-用python实现燕双鹰小游戏3

在前两个版本的更新后,越来越多内容,操作和运行也不方便,优化第三版本窗口可视化界面 本次版本更新使得可读性和可操作性大幅度增加,前面2版本可分别参考 我不是挂王-用python实现燕双鹰小游戏 和 我不是挂王-用python实现燕双鹰小游戏2 一.燕双鹰窗口可视化(燕双鹰3.0) 新燕双…

装饰(Decorator)模式可以在不修改对象外观和功能的情况下添加或者删除对象功能

试题(35)、(36)某系统中的文本显示类(TextView)和图片显示类(PictureView)都继承了组件类(Component),分别显示文本和图片内容,现需要…

深度学习基础概念【持续更新】

1. 梯度消失如果网络中某一层的激活函数(如 sigmoid 或 tanh)在输入较大的情况下有很小的梯度(比如接近零),那么当这些小的梯度通过多层反向传播时,它们会逐渐变得更小。这意味着在深层网络的前面几层&…

上下文工程:AI应用成功的关键架构与实践指南

在AI应用开发中,模型能力只决定性能上限,而上下文质量决定性能下限——上下文工程正是确保AI系统理解用户意图、生成准确响应的核心工程技术,已成为区分普通AI应用与卓越AI应用的关键因素。一、上下文工程:AI应用的新核心竞争力 1…

数据传输优化-异步不阻塞处理增强首屏体验

背景:主 project 页面中会将视频存储到云端后获得 ID ,然后用 ID 调用 后端API POST到数据库后拿到挂载页面URL,接着传入视频分享组件(由于视频分享子组件的目标是分享视频挂载页面,所以前置步骤不能少)con…

【芯片设计-信号完整性 SI 学习 1.0 -- SI 介绍】

文章目录一、SoC 设计验证阶段的 SI 测试主要工作举例二、芯片 Bringup 阶段的 SI 测试主要工作举例三、SI-PI 联合仿真主要内容举例四、整体总结一、SoC 设计验证阶段的 SI 测试 在 前硅阶段(pre-silicon),设计团队需要确保 SoC 与外设接口…

C语言链表设计及应用

链表链表节点设计链表项目链表中的传址调用检查申请空间链表尾插链表头插链表尾部删除链表头部删除链表的查找指定位置之前插入指定位置之后插入数据删除指定位置(节点)数据删除指定位置(节点)之后的数据链表的销毁前面学习了顺序…

使用 YAML 自动化 Azure DevOps 管道

1. 在 Azure DevOps 中设置 YAML 管道 开始之前,您需要拥有一个 Azure DevOps 帐户和一个 git 仓库。 要创建 YAML 管道, 1. 导航至 Azure DevOps → 选择您的项目 2. 前往“管道”→ 点击“新建管道” 3. 选择您的仓库(Azure Repos、GitHub 等) 4. 选择“Starter Pipelin…

基于Spring Boot的幼儿园管理系统

基于Spring Boot的幼儿园管理系统 源码获取:https://mbd.pub/o/bread/YZWXlZtsbQ 引言 在数字化转型的浪潮中,教育行业的信息化建设显得尤为重要。幼儿园作为基础教育的重要环节,其管理系统的现代化水平直接关系到教育质量和运营效率。本文…

【NVIDIA-B200】 ‘CUDA driver version is insufficient for CUDA runtime version‘

目录 一、错误核心原因 二、排查步骤 1. 检查当前驱动版本 2. 检查 CUDA 运行时版本 3. 验证驱动与 CUDA 的兼容性 三、解决方法 1. 确保驱动正确加载 2. 重新安装匹配的驱动与 CUDA 3. 验证环境正确性 四、关键注意事项 报错日志: bash nccl.sh ------------5.安…

Android中如何实现自动化测试

目录 前言: 一、方法介绍 1、UI Automator 3、shell脚本 二、shell脚本实现自动化测试原理和步骤 1、 原理 2、步骤 三、shell自动化测试实例 前言: 在开发项目的过程中,我们将某个阶段的需求完成并且提测,通常,在测试工程师更细致的测…