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

redis 缓存雪崩

在这里插入图片描述
Redis缓存雪崩指的是在Redis缓存系统中,大量的缓存数据在同一时间过期失效,导致大量原本可以从缓存获取的数据请求直接落到数据库上,造成数据库瞬间压力过大,甚至可能导致数据库崩溃,进而影响整个系统的正常运行。以下从缓存雪崩产生的原因和解决方案两方面进行介绍:

产生原因

  • 大量缓存集中过期:在某些业务场景下,可能会批量设置缓存的过期时间,比如在电商大促活动结束后,大量与活动相关的缓存数据同时过期,使得大量请求直接打到数据库。
  • 缓存服务器故障:如果Redis集群中某个节点或整个集群出现故障,导致缓存数据全部丢失或不可用,所有请求也会转而涌向数据库。

解决方案

  1. 分散过期时间:避免大量缓存同时过期,在设置缓存过期时间时,为每个缓存项添加一个随机的过期时间偏移量。例如,原本设置缓存过期时间为60分钟,可以改为在55到65分钟之间随机取值,这样可以让缓存过期时间更加分散,减轻数据库压力。
  2. 使用互斥锁:当缓存失效时,先获取一个互斥锁(如使用Redis的SETNX命令),只有获取到锁的请求才能去查询数据库并更新缓存,其他请求则等待一段时间后重试从缓存获取数据。这样可以保证在同一时间只有一个请求去查询数据库,避免大量请求同时穿透到数据库。示例代码如下(以Python和Redis为例):
import redis
import time

r = redis.Redis(host='localhost', port=6379, db=0)


def get_data_with_mutex(key):
    mutex_key = f'mutex:{key}'
    while True:
        # 尝试获取互斥锁
        if r.setnx(mutex_key, 1):
            try:
                data = r.get(key)
                if not data:
                    # 缓存不存在,查询数据库
                    data = get_data_from_db(key)
                    r.setex(key, 3600, data)  # 设置缓存
                return data
            finally:
                # 释放互斥锁
                r.delete(mutex_key)
        else:
            # 未获取到锁,等待重试
            time.sleep(0.1)


def get_data_from_db(key):
    # 实际从数据库查询数据的逻辑
    return f'data for {key}'
  1. 设置永不过期:对于一些不经常变化的数据,可以设置为永不过期(即不设置过期时间),或者通过其他机制(如消息队列、定时任务等)来异步更新缓存数据。这样可以避免因缓存过期导致的雪崩问题。
  2. 二级缓存:采用两级缓存架构,如一级缓存使用Redis,二级缓存可以使用本地缓存(如Python的functools.lru_cache)。当一级缓存失效时,先从二级缓存获取数据,如果二级缓存也没有,则查询数据库并更新两级缓存。这样可以在一定程度上减少直接对数据库的请求。
  3. 缓存预热:在系统启动阶段,提前将部分热点数据加载到缓存中,并设置合理的过期时间。这样可以避免系统刚上线时大量缓存未加载,导致请求直接打到数据库。
  4. 搭建高可用的Redis集群:使用Redis Sentinel或Redis Cluster等方式搭建高可用的Redis集群,确保即使某个节点出现故障,其他节点仍能正常提供缓存服务,减少因缓存服务器故障导致的雪崩问题。同时,配置合适的持久化策略(如RDB和AOF),以便在Redis重启后能够快速恢复缓存数据。

http://www.kler.cn/a/454129.html

相关文章:

  • “游戏信息化”:游戏后台系统的未来发展
  • Vue.js组件开发-实现访问页面自动获取数据
  • pdf有密码,如何实现pdf转换word?
  • 菜鸟带新鸟——基于EPlan2022的部件库制作(3D)
  • WordPress源码解析-数据库表结构
  • 【漫话机器学习系列】022.微积分中的链式求导法则(chain rule of Calculus)
  • 重装荣耀X14笔记本电脑踩坑记
  • Linux 线程池
  • RocketMQ的集群架构是怎样的?
  • 深度学习中的并行策略概述:4 Tensor Parallelism
  • 【ES6复习笔记】模板字符串(3)
  • 运行Zr.Admin项目(前端)
  • C++软件设计模式之类型模式和对象型模式
  • PDF书籍《手写调用链监控APM系统-Java版》第9章 插件与链路的结合:Mysql插件实现
  • 基于 Python 大数据的拼团购物数据分析系统的设计与实现
  • 路由器的原理
  • Axure10
  • 【无标题】学生信息管理系统界面
  • GitLab安装及使用
  • C++打造局域网聊天室第十三课: 任务栏托盘功能的实现
  • [2003].第2-01节:关系型数据库表及SQL简介
  • [bug]java导出csv用Microsoft Office Excel打开乱码解决
  • 【K8S问题系列 | 20 】K8S如何删除异常对象(Pod、Namespace、PV、PVC)
  • 各种网站(学习资源、常用工具及其他,持续更新中~)
  • Python - 获取当前函数中的所有参数信息(名称和值)
  • 【Rust自学】7.3. 路径(Path)Pt.2:访问父级模块、pub关键字在结构体和枚举类型上的使用