【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 result

def 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 random

r = 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 time

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LLMs之Agent之Lares:Lares的简介、安装和使用方法、案例应用之详细攻略

LLMs之Agent之Lares:Lares的简介、安装和使用方法、案例应用之详细攻略 导读:这篇博文介绍了 Lares,一个由简单的 AI 代理驱动的智能家居助手模拟器,它展现出令人惊讶的解决问题能力。 >> 背景痛点:每天都有新的…

快速集成外部业务数据:观测云如何颠覆传统监控的边界

01 传统监控的局限:被困在技术的“象牙塔” 过去的监控工具更多地服务于 IT 技术人员,就像是只为运维人员准备的“秘密花园”。服务器负载、网络延迟、系统资源——这些技术指标构成了一个封闭的世界,与业务层隔绝,就像是运维人员…

如何在Ubuntu中利用repo和git地址下载获取imx6ull的BSP

01-设置git的用户名和邮箱 git config --global user.name "suwenhao" git config --global user.email "2487872782qq.com"这里不设置的话后面在第5步的repo配置中还是会要求输入,而且以后进行相关操作都要输入,不妨现在就进行配置…

Linux-Ubuntu相关指令以及操作

一,Linux基础指令 二,文件系统结构 常用的U盘就是挂载在这个mdeia文件夹下,比如实现优盘分几个区,就要将在dev下优盘的驱动解除挂载在media,然后对其进行分区,再挂载回去,最后将其类型重新改为fat32格式&am…

二进制部署Prometheus+grafana+alertmanager+node_exporter

Prometheus 是一个开源的监控和告警工具包,旨在提供高可靠性和可扩展性。它最初由 SoundCloud 开发,现已成为云原生计算基金会(CNCF)的一部分。以下是 Prometheus 的一些关键特性和概念: 1. **时间序列数据库**&#…

使用springboot-3.4.1搭建一个netty服务并且WebSocket消息通知(适用于设备直连操作,以及回复操作)

引入最新版本 <!--websocket--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dependency>启动类加入 //netty 协议服务端口启动 NettyTcpHandler.start()…

vulnhub靶场【hacksudo】之2

前言 靶机&#xff1a;hacksudo-2 攻击&#xff1a;kali 都是采用虚拟机&#xff0c;网卡为桥接模式 主机发现 使用arp-scan -l或者netdiscover -r 192.168.1.1/24或者nmap和masscan等可以扫描网段的扫描工具&#xff0c;不过建议使用前两个即可&#xff0c;因为靶机与攻击…

Spring Boot助力,一键解锁招聘全流程信息精细化管理

2系统相关技术 2.1 Java语言介绍 Java是由SUN公司推出&#xff0c;该公司于2010年被oracle公司收购。Java本是印度尼西亚的一个叫做爪洼岛的英文名称&#xff0c;也因此得来java是一杯正冒着热气咖啡的标识。Java语言在移动互联网的大背景下具备了显著的优势和广阔的前景&#…

【设计模式系列】策略模式(二十四)

一、什么是策略模式 策略模式&#xff08;Strategy Pattern&#xff09;是软件设计模式中的一种行为型模式。它定义了一系列算法&#xff0c;并将每一个算法封装起来&#xff0c;使它们可以互换使用&#xff0c;算法的变化不会影响使用算法的用户。策略模式让算法的变化独立于…

《Java核心技术I》映射条目的原子更新

映射条目的原子更新 ConcurrentHashMap只有部分原子更新。 JavaAPI提供了一些新方法&#xff0c;例如&#xff1a;compute方法可以提供一个键和一个计算新值的函数。 map.compute(word,(k,v)->v null ? 1 : v1) 注释&#xff1a;ConcurrentHashMap中不允许有null值。很…

【Rive】波动文字

1 前言 本文将使用文本修改器&#xff08;Text Modifiers&#xff09;做文字动画&#xff0c;实现文字波动效果。 按以下步骤可以创建一个 Modifier Group 和 Range。 部分参数的释义如下。 Range: Modifier 作用的范围。Falloff: Modifier 在最大值时的范围&#xff0c;Fallo…

《庐山派从入门到...》初见

《庐山派从入门到...》初见 庐山派简介立创庐山派资源网站 庐山派个人分享&#xff0c;主要内容放到视频中&#xff0c;视频主要流程截图在博客上&#xff0c;所使用链接和代码也会放到博客中方便提取。希望小伙伴给我的视频点个关注谢谢小伙伴们。 《庐山派从入门到...》初见 …

现代软件开发技术 | 第2章:SpringMVC基础

文章目录 📚Spring MVC的工作原理📚Spring MVC的工作环境📚基于注解的控制器📚表单标签库与数据绑定🐇表单标签库🐇数据绑定📚JSON数据交互🐇JSON数据结构🐇JSON数据转换📚Spring MVC的基本配置🐇静态资源配置🐇拦截器配置🐇文件上传配置📚Spring …

【JavaWeb后端学习笔记】Java上传文件到阿里云对象存储服务

阿里云对象存储 1、创建阿里云对象存储节点2、上传文件2.1 修改项目配置文件2.2 定义一个Properties类获取配置信息2.3 准备一个alioss工具类2.4 创建注册类&#xff0c;将AliOssUtil 注册成Bean2.5 使用AliOssUtil 工具类上传文件2.6 注意事项 使用阿里云对象存储服务分为以下…

大模型 LMDeploy 量化部署

1 模型部署 定义&#xff1a; 在软件工程中&#xff0c;部署通常指的是将开发完毕的软件投入使用的过程。在人工智能领域&#xff0c;模型部署是实现深度学习算法落地应用的关键步骤。简单来说&#xff0c;模型部署就是将训练好的深度学习模型在特定环境中运行的过程。 场景…

Github 2024-12-01 开源项目月报 Top20

根据Github Trendings的统计,本月(2024-12-01统计)共有20个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目10TypeScript项目9Go项目2HTML项目1Shell项目1Jupyter Notebook项目1屏幕截图转代码应用 创建周期:114 天开发语言:TypeScript, Py…

调试玲珑应用

文章目录 一、在终端中使用 gdb 进行调试二、QtCreator 配置 以下教程以“构建工具”一节中提到的 linglong-builder-demo 项目为例。我们将项目放在 /path/to/project。参考教程操作时注意对路径进行替换。 由于玲珑应用运行在容器中&#xff0c;想要在宿主机上对其进行调试&…

Linux笔记-现场实施记录(找网口、挂载u盘)

2024-10-08 在项目现场&#xff0c;进行实施&#xff0c;在此记录下&#xff0c;方便以后查阅。记录2个点&#xff1b; 找网口 服务器开机后查下ifconfig。 看下网卡配的标识如eth0 再使用如下命令 ethtool -p eth0 30 此时物理网口会闪烁&#xff0c;此时再看下是哪一个…

C# (WinForms) 使用 iTextSharp 库将图片转换为 PDF

iTextSharp简介 iTextSharp 是一个开源的 .NET 库&#xff0c;主要用于创建和操作 PDF 文档。它是 iText 的 .NET 版本&#xff0c;iText 是一个广泛使用的 Java 库。iTextSharp 继承了 iText 的核心功能并进行了适应 .NET 平台的调整。 iTextSharp 的主要功能包括&#xff1a…

2020 年“泰迪杯”数据分析职业技能大赛A 题教育平台的线上课程智能推荐策略

2020 年“泰迪杯”数据分析职业技能大赛A 题教育平台的线上课程智能推荐策略 完整代码请私聊 博主 一、 背景 近年来&#xff0c;随着互联网与通信技术的高速发展&#xff0c;学习资源的建设与共享呈现出新的发展趋势&#xff0c;各种网课、慕课、直播课等层出不穷&#xff0c…