当前位置: 首页 > news >正文

【Redis】深入解析Redis缓存机制:全面掌握缓存更新、穿透、雪崩与击穿的终极指南

文章目录

    • 一、Redis缓存机制概述
      • 1.1 Redis缓存的基本原理
      • 1.2 常见的Redis缓存应用场景
    • 二、缓存更新机制
      • 2.1 缓存更新的策略
      • 2.2 示例代码:主动更新缓存
    • 三、缓存穿透
      • 3.1 缓存穿透的原因
      • 3.2 缓解缓存穿透的方法
      • 3.3 示例代码:使用布隆过滤器
    • 四、缓存雪崩
      • 4.1 缓存雪崩的成因
      • 4.2 缓解缓存雪崩的方法
      • 4.3 示例代码:缓存过期时间随机化
    • 五、缓存击穿
      • 5.1 缓存击穿的原因
      • 5.2 缓解缓存击穿的方法
      • 5.3 示例代码:使用互斥锁
    • 更多:Moss前沿AI
    • 六、结语

Redis,作为业内领先的开源内存数据存储系统,以其高性能、高可用性和丰富的数据结构,广泛应用于缓存、消息队列、实时统计等多个领域。然而,如何深入理解并有效运用Redis的缓存机制,解决缓存更新、缓存穿透、缓存雪崩与缓存击穿等问题,成为提升系统稳定性和响应速度的关键所在。本文将为您全面解析Redis缓存机制,助您掌握应对各种缓存问题的终极方法。

在这里插入图片描述

一、Redis缓存机制概述

Redis(Remote Dictionary Server)是一种基于内存的键值存储系统,支持多种数据结构,如字符串、哈希、列表、集合、有序集合等。其高效的读写性能使其成为缓存系统的首选。然而,光有高性能还不够,合理的缓存策略和机制设计,才能确保系统在高并发和大流量下依然稳定运行。

1.1 Redis缓存的基本原理

Redis通过将数据存储在内存中,极大地提高了数据访问速度。与传统的数据库相比,Redis的操作时间复杂度低,能够在毫秒级别内完成各种数据操作。同时,Redis支持持久化机制,如RDB快照和AOF日志,保障数据的持久性和高可用性。

1.2 常见的Redis缓存应用场景

  • 页面缓存:缓存动态生成的页面,减少数据库查询,提高页面加载速度。
  • 数据缓存:缓存热点数据,降低数据库压力,提升系统性能。
  • 分布式锁:利用Redis的原子操作,实现分布式系统中的锁机制。
  • 消息队列:基于Redis的发布/订阅模式,实现高效的消息传递。

二、缓存更新机制

在实际应用中,缓存数据与数据库数据的一致性是至关重要的。合理的缓存更新机制,能够确保数据的实时性和准确性。
在这里插入图片描述

2.1 缓存更新的策略

  • 定时刷新:设定缓存的过期时间,定期刷新缓存数据。这种方式实现简单,但可能导致缓存数据与数据库数据不一致。
  • 主动更新:当数据库数据发生变动时,主动更新缓存。这种方式能够保证缓存数据的实时性,但需要在代码中增加缓存更新逻辑。
  • 订阅发布机制:利用Redis的发布/订阅特性,当数据库数据更新时,发布更新消息,所有订阅者接收到消息后更新缓存。

2.2 示例代码:主动更新缓存

以下是一个使用Python和Redis实现的主动更新缓存的示例:

import redis
import pymysql# 连接Redis
r = redis.Redis(host='localhost', port=6379, db=0)# 连接MySQL
db = pymysql.connect(host='localhost', user='user', password='passwd', db='dbname')
cursor = db.cursor()def get_user(user_id):cache_key = f"user:{user_id}"user_data = r.get(cache_key)if user_data:return user_data# 缓存中没有,查询数据库cursor.execute("SELECT * FROM users WHERE id=%s", (user_id,))result = cursor.fetchone()if result:r.set(cache_key, result, ex=60)  # 设置缓存过期时间为60秒return resultdef update_user(user_id, data):# 更新数据库cursor.execute("UPDATE users SET name=%s WHERE id=%s", (data['name'], user_id))db.commit()# 更新缓存cache_key = f"user:{user_id}"r.set(cache_key, data, ex=60)

在上述代码中,当调用update_user函数更新用户数据时,既更新了数据库,也更新了Redis缓存,确保数据的一致性。

三、缓存穿透

缓存穿透是指查询一个根本不存在的数据,由于缓存和数据库都无法命中,导致所有请求都打到数据库,最终可能导致数据库宕机。
在这里插入图片描述

3.1 缓存穿透的原因

  • 非法请求:恶意攻击者利用不存在的URL或参数频繁访问后端数据库。
  • 数据查询失误:由于程序逻辑或数据错误,频繁查询不存在的数据。

3.2 缓解缓存穿透的方法

  • 使用布隆过滤器:在请求到达缓存层之前,使用布隆过滤器判断请求的数据是否存在,大幅减少无效请求。
  • 缓存空结果:对于不存在的数据,缓存一个空对象,并设置较短的过期时间,防止短时间内大量重复请求。
  • 限制请求频率:通过限流策略,限制单位时间内的请求次数,防止恶意攻击。

3.3 示例代码:使用布隆过滤器

以下是一个使用Redis和Python实现布隆过滤器来防止缓存穿透的示例:

from pybloom_live import BloomFilter
import redis# 初始化布隆过滤器
bf = BloomFilter(capacity=1000000, error_rate=0.001)# 假设我们已经加载了所有合法的user_id到布隆过滤器中
for user_id in get_all_user_ids():bf.add(user_id)# 连接Redis
r = redis.Redis(host='localhost', port=6379, db=0)def get_user(user_id):if user_id not in bf:return None  # 直接返回,不查询缓存和数据库cache_key = f"user:{user_id}"user_data = r.get(cache_key)if user_data:return user_data# 缓存中没有,查询数据库user = query_database(user_id)if user:r.set(cache_key, user, ex=60)else:r.set(cache_key, "", ex=30)  # 缓存空结果return user

在上述代码中,布隆过滤器预先加载了所有合法的user_id,当请求到达时,首先通过布隆过滤器判断用户ID是否存在,若不存在,直接返回,避免了无效的缓存和数据库查询。

四、缓存雪崩

缓存雪崩是指在同一时间内大量缓存同时失效,导致随后大量请求直接打到数据库,可能引起数据库崩溃。
在这里插入图片描述

4.1 缓存雪崩的成因

  • 缓存集中过期时间:大量缓存设置相同的过期时间,导致同一时间大量缓存失效。
  • 高并发访问:在流量高峰期,缓存失效后,短时间内大量请求涌向数据库。

4.2 缓解缓存雪崩的方法

  • 缓存过期时间随机化:为每个缓存设置不同的过期时间,避免同一时间大量缓存失效。
  • 提前预热缓存:在缓存即将失效时,提前刷新缓存,平滑缓存过期。
  • 限流与降级:当检测到缓存雪崩风险时,采取限流措施,并对部分功能进行降级处理,保护数据库。

4.3 示例代码:缓存过期时间随机化

以下是一个Python示例,演示如何为Redis缓存设置随机过期时间:

import redis
import randomr = redis.Redis(host='localhost', port=6379, db=0)def set_cache(key, value):# 设置过期时间为60秒到120秒之间的随机值expire_time = random.randint(60, 120)r.set(key, value, ex=expire_time)

通过为每个缓存设置不同的过期时间,有效避免了大规模缓存同时失效,从而减轻了缓存雪崩的风险。

五、缓存击穿

缓存击穿是指在缓存失效的同时,大量请求并发访问同一数据,造成数据库瞬时压力过大。
在这里插入图片描述

5.1 缓存击穿的原因

  • 热点数据:某些热点数据在高并发情况下,缓存失效后会有大量请求同时访问数据库。
  • 单点失效:缺乏有效的锁机制,导致多个请求同时查询数据并更新缓存。

5.2 缓解缓存击穿的方法

  • 互斥锁(Mutex):在缓存失效后,只有一个请求查询数据库并更新缓存,其他请求等待或直接失败。
  • 队列等待:将请求放入队列,由一个线程依次处理,防止数据库被瞬时洪水攻击。
  • 提前加载:对热点数据定期刷新缓存,减少缓存失效的概率。

5.3 示例代码:使用互斥锁

以下是一个使用Redis实现互斥锁来防止缓存击穿的示例:

import redis
import timer = redis.Redis(host='localhost', port=6379, db=0)def get_user(user_id):cache_key = f"user:{user_id}"user_data = r.get(cache_key)if user_data:return user_datalock_key = f"lock:{user_id}"# 尝试获取锁have_lock = r.set(lock_key, "1", nx=True, ex=5)if have_lock:try:# 查询数据库user = query_database(user_id)if user:r.set(cache_key, user, ex=60)else:r.set(cache_key, "", ex=30)return userfinally:r.delete(lock_key)else:# 等待一段时间后重试time.sleep(0.1)return get_user(user_id)

在上述代码中,当缓存失效后,首先尝试获取锁,只有获取到锁的请求才能查询数据库并更新缓存,其他请求等待一定时间后重新尝试,从而有效防止了缓存击穿。

更多:Moss前沿AI

【OpenAI】(一)获取OpenAI API Key的多种方式全攻略:从入门到精通,再到详解教程!!

【VScode】(二)VSCode中的智能AI-GPT编程利器,全面揭秘ChatMoss & ChatGPT中文版

【CodeMoss】(三)集成13个种AI模型(GPT4、o1等)、支持Open API调用、自定义助手、文件上传等强大功能,助您提升工作效率! >>> - CodeMoss & ChatGPT-AI中文版

六、结语

Redis作为高性能的内存数据库,在现代系统架构中扮演着至关重要的角色。然而,仅仅依赖其高效的存储能力并不足以保证系统的稳定与高效。合理设计缓存策略,深入理解并有效应对缓存更新、缓存穿透、缓存雪崩与缓存击穿等问题,是每一个开发者必备的技能。

相关文章:

【Redis】深入解析Redis缓存机制:全面掌握缓存更新、穿透、雪崩与击穿的终极指南

文章目录 一、Redis缓存机制概述1.1 Redis缓存的基本原理1.2 常见的Redis缓存应用场景 二、缓存更新机制2.1 缓存更新的策略2.2 示例代码:主动更新缓存 三、缓存穿透3.1 缓存穿透的原因3.2 缓解缓存穿透的方法3.3 示例代码:使用布隆过滤器 四、缓存雪崩4…...

SQL语法——DQL查询

1.查询: 基础查询: select 列名1,列名2 from 表名; # 输入列名为*时为全查 条件查询: select 列名 from 表名 where 条件; #条件中含字符串时为字符串...

云计算.运维.面试题

1、计算机能直接识别的语言( C )。 A、汇编语言 B、自然语言 C、机器语言 D、高级语言 2、应用软件是指( D )。 A、所有能够使用的软件 B、能被各应用单位共同使用的某种软件 C、所有计算机上都应使用的基本软件D、专门为某一应用目的而编制的软件 3、计算机的显示器是一…...

基于vue和vite的计算器

实现思路:1.撰写方案三次迭代(得到方案、项目结构、提问的prompt) 2. 功能实现 3. 优化迭代 计算器项目方案设计(阶段一) 一、项目基本信息 项目名称:基于 Vue 和 Vite 的计算器项目 技术栈: 前…...

《OpenCV:视觉世界的魔法钥匙》

《OpenCV:视觉世界的魔法钥匙》 一、OpenCV 是什么1. 起源与发展支持2. 特点与优势3. 编程语言支持 二、OpenCV 的发展历程1. 重要版本发布时间线2. 版本更新内容 三、OpenCV 的主要功能1. 图像处理2. 特征提取3. 目标检测4. 运动分析5. 人脸识别6. 其他功能 四、Op…...

部署kafka并通过python操作

目录 一、安装JDK1.81、检查服务器是否已安装JDK2、若已安装JDK,进行卸载3、更新yum源4、搜索JDK1.8安装包5、安装JDK1.86、查看是否安装成功7、配置环境变量 二、安装Kafka1、下载并解压kafka部署包至/usr/local/目录2、修改server.properties3、修改/etc/profile4…...

【JAVA】Java高级:数据库监控与调优:SQL调优与执行计划的分析

作为Java开发工程师,理解SQL调优和执行计划的分析是至关重要的。这不仅可以帮助我们提高数据库查询的效率,还能减少系统资源的消耗,提升整体应用的性能。 1. SQL调优的重要性 随着数据量的增加和用户请求的增多,数据库的性能问题…...

【单片机开发】MCU三种启动方式(Boot选择)[主Flash/系统存储器(BootLoader)/嵌入式SRAM]

目录 参考资料: 利用 Boot 选择不同的启动方式: 单片机的存储结构(主 FLASH/系统存储器/嵌入式 SRAM): 1. Cortex-M 内核芯片——启动原理: 1.1. 启动流程: 1.2. 根据单片机的存储器映射和架构图:启动…...

跨库移植 SQL

背景 应用程序可能要基于不同数据库工作,各种数据库的 SQL 语法大体一致,但仍有些差别,结果就要改造这些 SQL,而这事通常只能手工调整,工作量大还容易出错。 完全自动改造 SQL 几乎是无法做到的,毕竟各种…...

(软件测试文档大全)测试计划,测试报告,测试方案,压力测试报告,性能测试,等保测评,安全扫描测试,日常运维检查测试,功能测试等全下载

1. 引言 1.1. 编写目的 1.2. 项目背景 1.3. 读者对象 1.4. 参考资料 1.5. 术语与缩略语 2. 测试策略 2.1. 测试完成标准 2.2. 测试类型 2.2.1. 功能测试 2.2.2. 性能测试 2.2.3. 安全性与访问控制测试 2.3. 测试工具 3. 测试技术 4. 测试资源 4.1. 人员安排 4.2. 测试环境 4.2.…...

Vue前端开发-路由跳转及带参数跳转

在Vue 3中,由于没有实例化对象this,因此,无法通过this去访问 $route对象,而是通过导入一个名为 useRouter 的方法,执行这个方法后,返回一个路由对象,通过这个路由对象就可以获取到当前路由中的信…...

服务器上安装 Node.js

在服务器上安装 Node.js 的过程根据你使用的操作系统和环境可能会有所不同。以下是一些常见的 Linux 发行版(如 Ubuntu 或 CentOS)上的安装步骤。 在基于 Red Hat/CentOS 的系统上安装 Node.js 设置 EPEL 仓库 如果没有启用 EPEL (Extra Packages for E…...

在阿里云/Linux环境搭建Gitblit服务

在阿里云/Linux环境搭建Gitblit服务 1. 整体描述2. 前期准备3. 安装步骤3.1 下载gitblit3.2 上传gitblit3.3 解压文件3.4 修改文件配置3.5 启动gitblit3.6 安全组配置 4. 总结 1. 整体描述 前段时间买了一个阿里云服务器,2核2G,3M固定带宽的配置&#x…...

MicroBlaze软核开发(二):GPIO

实现功能:使用 MicroBlaze软核,配置GPIO用拨码开关控制LED灯 Vivado版本:2018.3 目录 引言 vivado部分: 一、配置GPIO 二、生成HDL文件编译 SDK部分: 一、导出硬件启动SDK 二、新建应用程序工程 三、编写程序代…...

threejs相机辅助对象cameraHelper

为指定相机创建一个辅助对象,显示这个相机的视锥。 想要在场景里面显示相机的视锥,需要创建两个相机。 举个例子,场景中有个相机A,想要显示相机A的视锥,那么需要一个相机B,把B放在A的后面,两个…...

Luma 视频生成 API 对接说明

Luma 视频生成 API 对接说明 随着 AI 的应用变广,各类 AI 程序已逐渐普及。AI 已逐渐深入到人们的工作生活方方面面。而 AI 涉及的行业也越来越多,从最初的写作,到医疗教育,再到现在的视频。 Luma 是一个专业高质量的视频生成平…...

服务器数据恢复—EVA存储硬盘磁头和盘片损坏离线的数据恢复案例

服务器存储数据恢复环境&故障: 一台HP EVA存储中有23块硬盘,挂接到一台windows server操作系统的服务器。 EVA存储上有三个硬盘指示灯亮黄灯,此刻存储还能正常使用。管理员在更换硬盘的过程中,又出现一块硬盘对应的指示灯亮黄…...

【Python】深入探索Python类型检查:掌握 `typing` 模块的高级用法

解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着代码复杂度的增加,类型安全性在现代开发中变得尤为重要。Python自3.5引入类型提示(type hints),为开发者提供了静态类型检查的能力,而typing模块则是这一系统的核心。本篇文章深入研究Python的类型提示及…...

Android学习15--charger

1 概述 最近正好在做关机充电这个,就详细看看吧。还是本着保密的原则,项目里的代码也不能直接用,这里就用的Github的。https://github.com/aosp-mirror 具体位置是:https://github.com/aosp-mirror/platform_system_core/tree/mai…...

顶会新宠!KAN-LSTM完美融合新方案

2024深度学习发论文&模型涨点之——KANLSTM KAN-LSTM混合预测模型是一种结合了自注意力机制(KAN, Key-attention network)和长短时记忆网络(LSTM)的深度学习模型,主要用于序列数据的预测任务,如时间序…...

大话软工笔记—需求分析概述

需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...

JS设计模式(4):观察者模式

JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中&#xff0…...