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

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

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

相关文章

ABAP - 系统集成之SAP的数据同步到OA(泛微E9)服务器数据库

需求背景 项目经理说每次OA下单都需要调用一次SAP的接口获取数据,导致效率太慢了,能否把SAP的数据保存到OA的数据库表里,这样OA可以直接从数据库表里获取数据效率快很多。思来想去,提供了两个方案。 在集群SAP节点下增加一个SQL S…

2023年华数杯数学建模A题隔热材料的结构优化控制研究解题全过程文档及程序

2023年华数杯全国大学生数学建模 A题 隔热材料的结构优化控制研究 原题再现: 新型隔热材料 A 具有优良的隔热特性,在航天、军工、石化、建筑、交通等高科技领域中有着广泛的应用。   目前,由单根隔热材料 A 纤维编织成的织物,…

MongoDB性能监控工具

mongostat mongostat是MongoDB自带的监控工具,其可以提供数据库节点或者整个集群当前的状态视图。该功能的设计非常类似于Linux系统中的vmstat命令,可以呈现出实时的状态变化。不同的是,mongostat所监视的对象是数据库进程。mongostat常用于…

SpringBoot 赋能:精铸超稳会员制医疗预约系统,夯实就医数据根基

1绪论 1.1开发背景 传统的管理方式都在使用手工记录的方式进行记录,这种方式耗时,而且对于信息量比较大的情况想要快速查找某一信息非常慢,对于会员制医疗预约服务信息的统计获取比较繁琐,随着网络技术的发展,采用电脑…

电子商务人工智能指南 3/6 - 聊天机器人和客户服务

介绍 81% 的零售业高管表示, AI 至少在其组织中发挥了中等至完全的作用。然而,78% 的受访零售业高管表示,很难跟上不断发展的 AI 格局。 近年来,电子商务团队加快了适应新客户偏好和创造卓越数字购物体验的需求。采用 AI 不再是一…

mock.js介绍

mock.js http://mockjs.com/ 1、mock的介绍 *** 生成随机数据,拦截 Ajax 请求。** 通过随机数据,模拟各种场景;不需要修改既有代码,就可以拦截 Ajax 请求,返回模拟的响应数据;支持生成随机的文本、数字…

优化LabVIEW数据运算效率的方法

在LabVIEW中进行大量数据运算时,提升计算效率并减少时间占用是开发过程中常遇到的挑战。为此,可以从多个角度着手优化,包括合理选择数据结构与算法、并行处理、多线程技术、硬件加速、内存管理和界面优化等。通过采用这些策略,可以…

从零开始学TiDB(1) 核心组件架构概述

首先TiDB深度兼容MySQL 5.7 1. TiDB Server SQL语句的解析与编译:首先一条SQL语句最先到达的地方是TiDB Server集群,TiDB Server是无状态的,不存储数据,SQL 发过来之后TiDB Server 负责 解析,优化,编译 这…

AI与低代码技术融合:如何加速企业智能化应用开发?

引言 随着全球数字化转型的步伐加快,企业在智能化应用开发方面面临着前所未有的挑战和机遇。传统的软件开发方式往往需要大量的技术人员、时间和资源,而在瞬息万变的市场环境中,这种模式显得效率低下且难以满足企业快速迭代和创新的需求。 与…

unity与android拓展

一.AndroidStudio打包 1.通过Unity导出Android Studio能够打开的工程 步骤 1.设置导出基本信息:公司名、游戏名、图标、包名等关键信息 2.在File——>Build Settings中,勾选 Export Project 选项 3.点击Export 导出按钮 2.在Android Studio中打开Un…

40分钟学 Go 语言高并发:服务注册与发现

服务注册与发现 一、系统架构设计 让我们先通过流程图了解服务注册与发现的整体架构: 二、核心组件实现 1. 服务注册中心 package discoveryimport ("context""sync""time" )// ServiceInstance 服务实例 type ServiceInstance…

ESP8266作为TCP客户端或者服务器使用

ESP8266模块,STA模式(与手机搭建TCP通讯,EPS8266为服务端)_esp8266作为station-CSDN博客 ESP8266模块,STA模式(与电脑搭建TCP通讯,ESP8266 为客户端)_esp8266 sta 连接tcp-CSDN博客…

基于DFA算法实现敏感词过滤

1、什么是DFA? DFA(Deterministic Finite Automaton),即确定有穷自动机。其特征为:有一个有限状 态集合和一些从一个状态通向另一个状态的边,每条边上标记有一个符号,其中一个状态是 初态&#…

详解MySQL安装

目录 Ubantu 1. 使⽤apt安装MySQL 2.查看MySQL状态 3. MySQL 安装安全设置 4.设置密码 卸载MySQL Centos 1. 确认当前的系统版本 2.下载MySQL源 3.安装MySQL 4.启动mysqld 5.查看MySQL状态 6.设置开机自启动 7.查看MySQL密码,并登录 8.修改密码 Ubant…

Android 实现中英文切换

在开发海外项目的时候,需要实现app内部的中英文切换功能,所有的英文都是内置的,整体思路为: 创建一个sp对象,存储当前系统的语言类型,然后在BaseActivity中对语言进行判断; //公共Activitypubl…

使用uniapp开发小程序场景:在百度地图上调用接口返回的设备相关信息并展示

首先在百度地图开发者平台注册微信小程序开发密钥下载百度地图SDK-bmap-wx.min.js,下载地址在项目入口index.html页面进行引入页面中进行调用&#xff0c;代码示例如下<map id"map" longitude"108.95" latitude"34.34" scale"3" :m…

如何使用brew安装phpredis扩展?

如何使用brew安装phpredis扩展&#xff1f; phpredis扩展是一个用于PHP语言的Redis客户端扩展&#xff0c;它提供了一组PHP函数&#xff0c;用于与Redis服务器进行交互。 1、cd到php某一版本的bin下 /usr/local/opt/php8.1/bin 2、下载 phpredis git clone https://githu…

【Vulkan入门】01-列举物理设备

目录 先叨叨git信息主要逻辑VulkanEnvEnumeratePhysicalDevices()PrintPhysicalDevices() 编译并运行程序 先叨叨 上一篇已经创建了VkInstance&#xff0c;本篇我们问问VkInstance&#xff0c;在当前平台上有多少个支持Vulkan的物理设备。 git信息 repository: https://gite…

写NFC标签支持Android安卓Ohos纯血鸿蒙唤醒微信小程序

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?spma21dvs.23580594.0.0.52de2c1b8bEEGz&ftt&id61539185785 Python languagecodestr "en".encode(gbk) titlestrself.lineEdit_title.text().strip().encode(gbk) uriheaderindex sel…

51c自动驾驶~合集39

我自己的原文哦~ https://blog.51cto.com/whaosoft/12707676 #DiffusionDrive 大幅超越所有SOTA&#xff01;地平线DiffusionDrive&#xff1a;生成式方案或将重塑端到端格局&#xff1f; 近年来&#xff0c;由于感知模型的性能持续进步&#xff0c;端到端自动驾驶受到了来…