Redis缓存雪崩、穿透、击穿原因分析和解决方案,附Redis管道使用技巧

2023-11-08

先给大家附上其他几篇文章,感兴趣的自行开车导航

Redis过期策略和持久化机制全面揭秘,教你如何合理配置

【深入浅出Redis 一】从版本特性到数据类型到线程模型,带你了解Redis的核心特性和应用场景!

一次redis OOM问题分析解决,rdbtools安装分析redis内存

Redis管道及缓存问题解析

一、什么是Redis管道

Redis管道(pipeline)是一种在网络层面上实现的批量操作机制,它可以将多个命令一次性发送给Redis服务器,而不需要等待每个命令的响应。这样可以减少客户端和服务器之间的网络通信次数,提高命令执行效率。

Redis管道的原理是基于TCP协议的请求/响应模型,即客户端发送一个请求后,必须等待服务器的响应才能发送下一个请求。如果客户端有多个请求要发送,那么就会产生多次网络往返延迟(RTT),影响性能。

而通过管道技术,客户端可以将多个请求打包成一个数据包发送给服务器,服务器也会将多个响应打包成一个数据包返回给客户端,从而减少网络延迟。并且有些场景也避免了事务问题,比如设置key和设置时间

二、如何使用Redis管道

使用Redis管道非常简单,只需要在发送命令之前调用pipeline()方法,创建一个管道对象,然后将命令添加到管道对象中,最后调用execute()方法执行所有命令并返回结果列表。下面是一个java示例:

Jedis jedis = new Jedis("localhost"); 
Pipeline p = jedis.pipelined(); 
p.set("foo","bar"); p.get("foo"); 
List<Object> results = p.syncAndReturnAll();

需要注意的是,使用管道并不保证原子性,即如果有其他客户端在管道执行过程中修改了数据,那么可能会影响管道中的命令结果。如果需要保证原子性,可以使用事务(transaction)或Lua脚本。

什么是缓存雪崩、缓存穿透、缓存击穿

Redis作为目前使用最广泛的缓存,相信大家都不陌生。但是使用缓存并没有这么简单,还要考虑缓存雪崩、缓存击穿、缓存穿透的问题,这些问题都可能导致大量请求直接打在数据库上,造成数据库压力过大甚至宕机。

那么这些问题分别是什么意思呢?

缓存雪崩

缓存雪崩是指当某一个时刻出现大规模的缓存失效的情况(比如Redis宕机或者大量key同时过期),导致大量请求直接打在数据库上,造成数据库压力巨大甚至宕机。这就像一场雪崩一样,一旦发生就很难控制。

缓存穿透

缓存穿透是指当用户请求的数据在缓存和数据库中都不存在时(比如请求一个不存在的id),导致每次请求都会到数据库中查询,从而给数据库造成压力。这就像穿透了缓存一样,直接访问数据库。

缓存击穿

缓存击穿是指当一个热点key在缓存中过期时,同时有大量请求过来查询这个key,导致大量请求直接打在数据库上,造成数据库压力剧增。这就像击穿了缓存一样,直接访问数据库。

四、如何解决缓存问题

说到底就是最终落到数据库了,如果有大量请求数据库就会被群殴致死,针对上面三种缓存问题,我们可以采用不同的解决方案,下面分别介绍。

解决缓存雪崩

解决缓存雪崩的关键在于避免大规模的key同时失效,有几种方法:

  • 设置不同的过期时间。避免缓存设置相同的过期时间,可以在设置过期时间时增加一个随机值,使得过期时间均匀分布。(推荐)
  • 数据预热。对于即将到来的大流量请求,可以提前将数据加载到缓存中,并设置不同的过期时间。
  • 保证Redis服务高可用。为了防止Redis宕机导致缓存雪崩的问题,可以搭建Redis集群或哨兵模式,提高Redis的容灾性。
  • 使用熔断机制。当流量到达一定的阈值时,可以直接返回“系统拥挤”之类的提示,防止过多的请求打在数据库上。
  • 提高数据库的容灾能力。可以使用分库分表、读写分离、负载均衡等策略,提高数据库的承载能力和稳定性。

解决缓存穿透

解决缓存穿透的关键在于避免查询不存在的数据,有以下几种方法:

  • 参数校验。对用户请求的参数进行校验,对于明显错误或非法的参数,直接拦截返回。
  • 缓存空值。对于查询为空的数据,也可以将其缓存在Redis中,并设置一个较短的过期时间(比如30秒),这样可以防止短时间内大量重复查询。
  • 使用布隆过滤器。布隆过滤器是一种数据结构,利用极小的内存,可以判断大量数据“一定不存在或者可能存在”。对于缓存穿透,我们可以将所有可能存在的key哈希到一个足够大的布隆过滤器中,用户请求时先判断key是否在布隆过滤器中,如果不在就直接返回。(推荐)

解决缓存击穿

解决缓存击穿的关键在于避免热点key失效时造成大量请求打在数据库上,有以下几种方法:

  • 设置热点数据永不过期。对于某些需要频繁访问的数据,可以将其设置为永不过期的key,当然这种方式比较粗暴,对于某些业务场景是不适合的。
  • 定时更新。对于某些有固定过期时间的热点数据,可以在其快要过期前通过定时任务去更新它,并重新设置过期时间。
  • 使用互斥锁。当缓存失效时,只有拿到锁的请求才能去查询数据库并更新缓存,其他请求则等待或重试。这样可以降低同时打在数据库上的请求数量。

缓存和数据库双写一致性问题

在使用Redis作为缓存时,我们通常需要在数据发生变化时,同时更新缓存和数据库,以保证数据的一致性。但是由于网络延迟或者其他原因,可能会导致缓存和数据库的数据不一致。

例如,如果先更新缓存再更新数据库,那么如果缓存更新成功而数据库更新失败,就会导致缓存中的数据是脏数据。

如果先更新数据库再更新缓存,那么如果数据库更新成功而缓存更新失败,就会导致缓存中的数据是旧数据。

那么如何解决这个问题呢?

解决方案

针对这个问题,有几种解决方案:

  • 先删除缓存再更新数据库。这种方式可以保证数据库中的数据是最新的,但是可能会导致短时间内的缓存不命中,增加数据库压力。为了避免这个问题,可以在删除缓存后延迟一段时间(比如1秒)再更新数据库,这样可以减少其他请求查询到空缓存的概率。
  • 先更新数据库再删除缓存。这种方式可以保证缓存中的数据是最新的,但是可能会导致删除缓存失败,导致缓存过期。为了避免这个问题,可以在删除缓存后延迟一段时间(比如1秒)再次删除缓存,减少其他请求查询到过期缓存的概率。
  • 使用消息队列。将更新操作放入消息队列中,保证顺序执行,并且可以重试失败的操作。这样可以保证最终一致性,但是可能会增加系统复杂度和延迟。
  • 使用分布式锁。在更新操作前获取一个分布式锁,保证同一时刻只有一个请求能够更新数据,并且在更新完成后释放锁。这样可以保证强一致性,但是可能会降低并发性能和可用性

开发过程中看起来我们都是先处理数据再删缓存的

其他问题

  • 缓存穿透、击穿、雪崩的监控和预警。为了及时发现和处理缓存问题,需要对Redis的性能和状态进行监控和预警,比如监控Redis的QPS、响应时间、内存使用率、命中率等指标,当发现异常时及时报警并处理。
  • 缓存的合理使用。不是所有的数据都适合放入缓存中,需要根据数据的访问频率、更新频率、大小等因素进行权衡。一般来说,适合放入缓存的数据应该满足以下条件:
    • 访问频率高,更新频率低。这样可以提高缓存命中率,减少数据库压力。
    • 数据量小,计算量大。这样可以减少网络传输开销,提高计算效率。
    • 数据一致性要求不高。这样可以容忍缓存和数据库之间的短暂不一致。

业务场景举例

下面举几个使用Redis作为缓存的业务场景:

  • 商品详情页。商品详情页是电商网站中最常访问的页面之一,每个商品都有一个唯一的id作为key,商品的基本信息、库存、评价等作为value。这些数据一般不会频繁变化,但是访问量很大,所以适合放入Redis中作为缓存。当用户访问某个商品详情页时,先从Redis中查询,如果命中则直接返回,如果不命中则从数据库中查询,并将结果放入Redis中,并设置一个过期时间(比如1小时)。当商品信息发生变化时(比如库存变化),需要同时更新数据库和缓存。
  • 热门排行榜。热门排行榜是展示某个维度下最受欢迎的内容的列表,比如电影排行榜、音乐排行榜、新闻排行榜等。这些数据一般会根据某个指标(比如评分、播放量、点击量等)进行排序,并定期更新。这些数据适合放入Redis中作为缓存,因为它们访问量大,计算量大,数据量小。可以使用Redis的有序集合(sorted set)来实现排行榜功能,每个元素对应一个内容id,分数对应一个指标值。当用户访问某个排行榜时,先从Redis中查询,如果命中则直接返回,如果不命中则从数据库或其他服务中查询,并将结果放入Redis中,并设置一个过期时间(比如10分钟)。当内容的指标值发生变化时(比如评分变化),需要同时更新数据库和缓存。
  • 验证码。验证码是一种用于防止机器人或恶意用户的一种安全机制,一般在用户注册、登录、下单等场景中使用。验证码一般有一个有效期(比如5分钟),并且只能使用一次。这些数据适合放入Redis中作为缓存,因为它们访问频率高,更新频率高,数据量小,数据一致性要求不高。可以使用Redis的字符串(string)来实现验证码功能,每个key对应一个用户id或手机号,value对应一个验证码。当用户请求发送验证码时,生成一个随机的验证码,并将其存入Redis中,并设置一个过期时间(比如5分钟)。当用户输入验证码时,先从Redis中查询,如果命中则验证是否正确,如果不命中则提示验证码已过期或不存在。当验证码验证成功或失败时,需要删除Redis中的key。

今天就介绍到这里,感谢大家

感兴趣的自行开车导航

Redis过期策略和持久化机制全面揭秘,教你如何合理配置

【深入浅出Redis 一】从版本特性到数据类型到线程模型,带你了解Redis的核心特性和应用场景!

一次redis OOM问题分析解决,rdbtools安装分析redis内存

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Redis缓存雪崩、穿透、击穿原因分析和解决方案,附Redis管道使用技巧 的相关文章

  • 为什么我不能让单个 Redis 客户端在同一连接中充当 PUB 和 Sub ?

    我的思维模型是 聊天 我订阅了某个频道 并且可以向该频道发布消息 由于 pub sub 是异步的 因此发布的消息可能随时出现 包括当您期望命令响应时 尽管 Redis 是单线程的 通常会阻止此类事情 但网络延迟可能会导致一些有趣的影响 根据
  • 如何判断sidekiq是否连接到redis服务器?

    使用控制台 如何判断 sidekiq 是否连接到 Redis 服务器 我希望能够做这样的事情 if sidekiq is connected to redis psuedo code MrWorker perform async do wo
  • Redis多插入问题

    我尝试多次插入 但它给了我错误 http pastie org 7337421 http pastie org 7337421 cat mass insert txt 3 r n 3 r nSET r n 3 r nkey r n 5 r
  • StackExchange.Redis 和 StackExchange.Redis.StrongName 之间有什么区别?

    当我关注Azure时文档 http azure microsoft com en us documentation articles cache dotnet how to use azure redis cache 关于如何在Azure
  • socket.io redis 和内存泄漏

    我的socket io版本是 电子邮件受保护 cdn cgi l email protection and 电子邮件受保护 cdn cgi l email protection 我在 Windows 上 在某些地方 我看到问题已得到解决 我
  • 如何从 python 将无穷大传递给 redis?

    我正在使用 redis py 并希望将 inf 和 inf 与 ZRANGEBYSCORE 一起使用 我尝试使用 inf 的字符串和浮点来执行此操作 但它们返回一个空集 我怎样才能做到这一点 EDIT 我尝试执行以下命令 redis Str
  • python 3.5 中的 json.loads 和 Redis

    我使用 json dumps 创建了一个 JSON 对象 并在 Redis 列表中将其 RPUSH ed 当使用 LRANGE redis lrange 返回 JSON 时 我收到一个二进制字符串 b si 00 ff 所以 json lo
  • 使用 AWS ElastiCache 请求中的 Airflow CROSSSLOT 密钥未散列到同一插槽错误

    我在 AWS ECS 上运行 apache airflow 1 8 1 并且有一个 AWS ElastiCache 集群 redis 3 2 4 运行 2 个分片 2 个启用多可用区的节点 集群 Redis 引擎 我已经验证气流可以毫无问题
  • 如何让客户端下载动态生成的非常大的文件

    我有一个导出功能 可以读取整个数据库并创建一个包含所有记录的 xls 文件 然后文件被发送到客户端 当然 导出完整数据库的时间需要大量时间 并且请求很快就会以超时错误结束 处理这种情况的最佳解决方案是什么 例如 我听说过使用 Redis 创
  • Redis hash写入速度非常慢

    我面临一个非常奇怪的问题 使用 Redis 时 我的写入速度非常糟糕 在理想的情况下 写入速度应该接近 RAM 上的写入速度 这是我的基准 package redisbenchmark import redis clients jedis
  • Spring Data Redis JedisConnectionException:流意外结束

    雷迪斯3 0 5Spring数据Redis 1 3 6绝地武士2 6 3 我们的 Web 应用程序通过 pub sub 从 Redis 接收数据 还以键 值对的形式在 Redis 上执行数据读 写 读 写发生在监听线程 独立监控线程和htt
  • 如何测试我的 Redis 缓存是否正常工作?

    我已经安装了 django redis cache 和 redis py 我遵循了 Django 的缓存文档 据我所知 以下设置就是我所需要的 但我如何判断它是否正常工作 设置 py CACHES default BACKEND redis
  • SignalR 无法连接到 SSL 上的 Azure Redis

    我目前在 Azure 上托管我的 redis 缓存服务器 并让 signalR 依赖它作为骨干 使用以下内容 GlobalHost DependencyResolver UseRedis 服务器 端口 密码 eventKey 这可以在端口
  • 使用 Redis 命令 incr 和 expire 时的竞争条件

    根据redis文档 http redis io commands incr http redis io commands incr 在段落模式 速率限制器 2 较短的版本代码 value INCR ip IF value 1 THEN EX
  • Redis Docker compose无法处理RDB格式版本10

    我无法在 docker compose 文件中启动 redis 容器 我知道docker compose文件没问题 因为我的同事可以成功启动项目 我读到有一个删除 dump rdb 文件的解决方案 但我找不到它 我使用Windows机器 任
  • Node Js:Redis 作业在完成其任务后未完成

    希望你们做得很好 我在我的 Nodejs 项目中实现了 BullMQ Bull 的下一个主要版本 来安排发送电子邮件的作业 例如 发送忘记密码请求的电子邮件 所以 我编写了如下所示的代码 用户服务 await resetPasswordJo
  • Lua中按字符分割字符串

    我有像这样的字符串 ABC DEF 我需要将它们分开 字符并将两个部分分别分配给一个变量 在 Ruby 中 我会这样做 a b ABC DEF split 显然Lua没有这么简单的方法 经过一番挖掘后 我找不到一种简短的方法来实现我所追求的
  • Java 将字节转换为二进制安全字符串

    我有一些以字节为单位的数据 我想将它们放入Redis中 但是Redis只接受二进制安全字符串 而我的数据有一些二进制非安全字节 那么如何将这些字节转换为二进制安全字符串以便将它们保存到 Redis 中呢 Base64 对我有用 但它使数据更
  • 有没有办法用Lettuce自动发现Redis集群中新的集群节点IP

    我有一个Redis集群 3主3从 运行在一个库伯内斯簇 该集群通过Kubernetes 服务 Kube 服务 我将我的应用程序服务器连接到 Redis 集群 使用Kube 服务作为 URI 通过 Redis 的 Lettuce java 客
  • redis - 使用哈希

    我正在使用 redis 为我的 Web 应用程序实现社交流和通知系统 我是 redis 的新手 我对哈希值及其效率有一些疑问 我读过这篇很棒的文章Instagram 帖子 http instagram engineering tumblr

随机推荐

  • ImportError: Could not find ‘cudart64_90.dll‘错误成功解决方法

    出现该问题是在运行tensorflow项目时出现的 原因有两个方面 第一个版本要对应 我的是tensorflow gpu 1 8 0 python3 6 cuda9 0 还需要cudnn解压的三个文件夹下面的三个文件考到CUDA v9 0
  • 处理 Comparable接口不严谨导致Comparison method violates its general contract!

    本文主旨是记录问题解决过程 出错的日志 Shutting down VM beginning of crash FATAL EXCEPTION main Process com gezbox deliver PID 25572 java l
  • android学习笔记——GridView控件(九宫格布局)

    GridView跟ListView都是比较常用的多控件布局 而GridView更是实现九宫图的首选 先来介绍一下要做的工作 有一个完整的思路 1 在activity main xml中加一个GridViwe 2 编写一个自定义的Adapte
  • 论文笔记:MEASURING DISENTANGLEMENT: A REVIEW OF METRICS

    0 摘要 学习解缠和表示数据中的变化因素是人工智能中的一个重要问题 虽然已经取得了许多关于学习这些表示的进展 但如何量化解缠仍然不清楚 虽然存在一些度量标准 但对它们的隐含假设 真正衡量的内容以及限制了解甚少 因此 当比较不同的表示时 很难
  • 基于深度强化学习的柔性作业车间动态调度

    文献来源 International Journal of Production Research 2022 南洋理工大学 IJPR 2022 Full article Deep reinforcement learning for dyn
  • JPS命令的安装和使用

    一 简介 jps Java Virtual Machine Process Status Tool 是JDK 1 5提供的一个显示当前所有java进程pid的命令 简单实用 非常适合在linux unix平台上简单察看当前java进程的一些
  • android NDK编译openblas和向量检索库faiss

    设置android SDK和NDK路径 例如 export SDK ROOT root codes my sdk sdk export NDK ROOT root codes my sdk sdk ndk 24 0 8215888 sdk和
  • 自制带串口的J-Link OB 072

    自制带串口的J Link OB 072 普通的三线J link不带串口 使用起来比较麻烦 于是找资料自制了一个J Link OB 072 主芯片是stm32f072c8t6 带串口 使用方便 先上图 自带信仰加持 一遍调通 急急如律令 依然
  • vue 高德地图添加放大缩小地图、转盘工具

    新建文件 amap vue
  • Guided Diffusion/Diffusion Models Beat GANs on Image Synthesis (Paper reading)

    Guided Diffusion Diffusion Models Beat GANs on Image Synthesis Paper reading Prafulla Dhariwal OpenAI NeurlPS2021 Cited
  • JavaScript——大数组的合并问题及不同数组合并方法的探究

    JavaScript 大数组的合并问题及不同数组合并方法的探究 最近在处理模型数据的时候出现了一个问题 当合并不同模型的vertex等数据的时候 从网上查了查都说Array prototype push 这个好 结果我使用了这个方法却报错了
  • VUE的项目中怎样修改浏览器窗口的 LOGO

    vue项目如何修改上图浏览器的标题栏的图标 在public目录中的index html添加如下代码 注意logo svg是图片 图片位置在public目录下
  • 【直接收藏】前端 VUE 高阶面试题(一)

    1 说说vue动态权限绑定渲染列表 权限列表渲染 首先请求服务器 获取当前用户的权限数据 比如请求 this http get rights list 获取到权限数据之后 在列表中使用v if v if else的组合来展示不同的内容
  • 性能测试常见问题分析

    性能测试常见问题分析 1 请你个人描述一下性能测试的意义和作用 说出因性能不良造成的质量事故 2 如何进行性能测试 请说出整体的性能测试流程 a 分析测试范围 测试对象 如频繁使用的功能 频繁调用的接口 大量数据库读写操作多的功能 大量读写
  • 信息组织川大972

    网络信息组织 1 网络信息环境 1 1 网络发展的三个阶段 2 语义网信息组织 2 1 万维网与语义网 2 2 语义网技术架构 2 3 本体 2 4 关联数据 2 5 网站信息架构 3 Web2 0信息组织方法 3 1 标签法 3 2 Wi
  • 多元Huffman编码问题

    题目链接 题意 最多可以让k堆合并 每一次合并的花费为河合并堆的数量 问最多和最少的花费 题解 最少的花费一定是每次合并的堆数尽可能多 这样我们就会减少前面已经合并的堆的重复计算 所以 每次合并k堆时最少 每次合并2堆时最大 另外 最少的时
  • [WTL] STLport安装指南

    STLport安装指南STLport 4 6 是完全兼容ANSI C 标准的类库 This distribution contains STLport sources only no binaries To use STLport iost
  • Word文件删除后怎么恢复?好用的恢复方法分享

    Word文件删除后怎么恢复 在工作和学习的过程中 我们难免会遇到丢失数据的情况 比如有时候不小心删除了Word文件 或者Word文件在操作过程中意外卡顿导致丢失 有什么好方法恢复呢 下面就一起来了解下 遇到Word文件数据丢失不要慌张 首先
  • Java项目的开发流程

    一个java开发项目过程 1 项目启动 1 项目组成立 公司成员 客户成员 2 制定项目预期目标 3 制定项目计划周期 4 建立好项目组成员沟通机制 2 需求调研 1 创建调研计划 协调调研时间 2 收集客户资料 获取客户需求 所有的资料都
  • Redis缓存雪崩、穿透、击穿原因分析和解决方案,附Redis管道使用技巧

    先给大家附上其他几篇文章 感兴趣的自行开车导航 Redis过期策略和持久化机制全面揭秘 教你如何合理配置 深入浅出Redis 一 从版本特性到数据类型到线程模型 带你了解Redis的核心特性和应用场景 一次redis OOM问题分析解决 r