文章 557
评论 5
浏览 215267
Redis 大 Key 热删除阻塞主线程:DEL 命令卡顿?UNLINK 异步清理 + 分片扫描方案

Redis 大 Key 热删除阻塞主线程:DEL 命令卡顿?UNLINK 异步清理 + 分片扫描方案

一、问题背景:生产环境的"定时炸弹" 凌晨 3 点,线上 Redis 突然出现大量请求超时,监控告警疯狂刷屏。排查发现: Redis 主线程 CPU 使用率飙升至 100% 大量命令堆积,响应时间超过 10 秒 应用服务出现雪崩,数据库连接池打满 根因分析:运维人员执行了一条 DEL big_hash_key 命令,该 Key 包含 500 万条字段,Redis 主线程需要遍历所有字段并逐一释放内存,导致阻塞长达 15 秒。 这就是 Redis 大 Key 删除的"阻塞陷阱"——看似简单的删除操作,背后隐藏着巨大的性能风险。 二、核心概念:DEL 与 UNLINK 的本质区别 2.1 DEL 命令的工作机制 DEL big_key 执行过程: ┌────────────────────────────────────────────────────────────────┐ │ Redis 主线程 │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ 1. 查找 key 的内存结构 │ │ │....

Redis 内存碎片化治理:used_memory 低却 OOM?内存碎片整理 + 对象池优化

Redis 内存碎片化治理:used_memory 低却 OOM?内存碎片整理 + 对象池优化

朋友公司的 Redis 集群监控上 used_memory 才 4GB,但 used_memory_rss 已经到了 8GB——是 used 的两倍。运维加了内存,过两个月又一样。最离谱的是有一次 used_memory 只有 2GB,Redis 却报了 OOM。排查发现内存碎片率 3.5,8GB 的物理内存被碎片占了一半多。 这就是 Redis 的内存碎片问题。used_memory 是你存进去的有用数据,used_memory_rss 是 Redis 实际向操作系统申请的内存。两者之间的差,就是碎片。 今天聊聊怎么用 Redis 自带的内存碎片整理和对象复用,把碎片率降到 1.1 以下。 碎片怎么来的 Redis 的内存分配是 jemalloc 管理的。当你反复写入和删除不同大小的 Key,就会出现这样的场景: 内存布局(简化): |AAAA| 空闲 |BB| 空闲 |CCCC| 空闲 |DD| 空闲 |... 删掉的 Key 留下的空隙不够大,放不下新的 Key。新 Key 只能往后申请新内存。结果就是 used 没涨多少,rss 一直涨。 碎片率计算公式: mem_fra....

热点 Key 自动发现与本地缓存:Redis 热键打爆?Caffeine 二级缓存+过期抖动防雪崩!

热点 Key 自动发现与本地缓存:Redis 热键打爆?Caffeine 二级缓存+过期抖动防雪崩!

大促的时候,运营在首页挂了一个爆款商品。瞬间几十万用户涌进来,同一个商品详情接口被疯狂调用。Redis 里这个商品的缓存 Key 被打到单节点 QPS 上限,响应时间从 1ms 飙升到 50ms,Redis 线程池打满,带着其他 Key 的请求也一起慢了。一块热铁掉进水里,整锅水都烫了。 这就是典型的热点 Key 问题。一个 Key 太热,把 Redis 单节点打穿了。因为 Redis 是单线程处理命令的,一个慢不会拖累别的,但如果请求量超过这个单节点的处理能力上限,所有请求都得排队。 今天聊聊怎么用 Caffeine 本地缓存做二级缓存,配合过期时间抖动防止缓存雪崩。 热点 Key 为什么难搞 先搞清楚热点 Key 的问题本质。正常缓存访问是这样的: 请求 → Redis → 命中 → 返回(1ms) 热点 Key 的情况下: 1000 个并发请求 → Redis 同一个 Key │ └─ 1000 次网络 IO(即使是 Redis,单节点也有处理上限) 问题不在"数据能不能被缓存",而在"所有请求都打到了同一个 Redis 节点上"。如果你的 Redis 是集群模式,这个热点....

断点续传进度持久化:上传中断后从头开始?Redis 记录分片状态,秒级续传!

断点续传进度持久化:上传中断后从头开始?Redis 记录分片状态,秒级续传!

公司做视频平台,用户上传一个 2GB 的素材文件,进度条跑到 95%,浏览器崩了。刷新页面重新上传,进度条又从 0% 开始。用户直接关了页面,再也没回来。 后来加了断点续传。用户重新打开页面,后端一问 Redis——"这个文件你上次传了 38 个分片,还差 2 个",直接从第 39 片开始传。3 秒搞定,用户甚至没注意到断过。 大文件上传这种事,不怕慢,怕的是断了之后要从头再来。今天聊聊怎么用 Redis 记录分片上传状态,实现真正的秒级续传。 先说清楚:为什么大文件上传非得分片 一个 2GB 的文件你不可能一口气传上去。网络稍微波动一下,整个 HTTP 请求就废了,2GB 白传。 所以业内的标准做法是分片上传:客户端把文件切成小块(比如每片 5MB),一片一片发。服务端收齐所有分片后,按顺序合并成完整文件。 客户端: 文件 2GB → 切成 400 片,每片 5MB 上传过程: 上传第 1 片 ✓ 上传第 2 片 ✓ ... 上传第 399 片(网络断了!)✗ 上传第 400 片 ✗ 服务端: 收到 398 片 等待第 399、400 片(永远等不到) 分片之后,问题就变成了....

Redis BigKey 在线拆分:Value 超 10MB 阻塞主线程?Hash 槽化迁移,零停机优化!

Redis BigKey 在线拆分:Value 超 10MB 阻塞主线程?Hash 槽化迁移,零停机优化!

做过 Redis 开发的同学肯定都遇到过 BigKey 问题:某个 Key 的 Value 太大,导致读取时阻塞主线程,整个 Redis 服务响应变慢甚至超时。我之前就遇到过这样一个案例:一个用户的购物车数据用单个 Hash 存储,随着时间推移数据越来越多,最终这个 Key 的 Value 达到了 15MB,每次读取都会导致 Redis 阻塞 500ms+,严重影响了系统性能。 今天我们就来聊聊 Redis BigKey 的危害,以及如何用 Hash 槽化迁移的方式实现零停机拆分。 BigKey 的危害 1. 什么是 BigKey BigKey 定义: - String 类型:Value 大小超过 1MB - Hash/List/Set/ZSet:元素数量超过 1000 个 常见场景: - 用户购物车:一个 Hash 存储所有商品 - 排行榜:一个 ZSet 存储所有用户分数 - 消息队列:一个 List 存储大量消息 - 配置中心:一个 String 存储超大配置 2. BigKey 的性能问题 性能影响分析: 1. 读取阻塞 - GET bigkey → 一次性读取 10MB+ ....

SpringBoot + Redis 缓存雪崩防护:大量 Key 同时过期?随机偏移 + 互斥重建双保险

SpringBoot + Redis 缓存雪崩防护:大量 Key 同时过期?随机偏移 + 互斥重建双保险

问题背景 在使用 Redis 作为缓存时,缓存雪崩是一个常见的性能问题。当大量缓存 Key 在同一时间过期时,会导致以下问题: 数据库压力剧增:所有请求都会直接访问数据库,导致数据库过载 系统响应变慢:数据库处理能力有限,无法处理大量并发请求 服务雪崩:系统可能因此崩溃,影响整个应用的可用性 用户体验下降:响应时间变长,甚至出现超时 缓存雪崩的常见原因包括: 集中过期:大量缓存 Key 设置了相同的过期时间 缓存预热:系统启动时批量加载缓存,设置了相同的过期时间 缓存失效:Redis 服务重启或网络故障导致缓存全部失效 热点数据:热点数据的过期时间集中,导致大量请求同时回源 核心概念 缓存雪崩 缓存雪崩是指在某一时间段内,大量缓存 Key 同时过期或失效,导致所有请求都直接访问数据库,造成数据库压力剧增的现象。 随机偏移 随机偏移是指在设置缓存过期时间时,添加一个随机值,使缓存的过期时间分散,避免集中过期。 互斥重建 互斥重建是指在缓存失效时,只有一个线程去重建缓存,其他线程等待或返回旧值,避免多个线程同时重建缓存导致的数据库压力。 缓存穿透 缓存穿透是指查询一个不存在的数据,....

SpringBoot + 缓存一致性双写策略 + 延迟双删:先更新 DB 再删缓存,防脏读实战方案

SpringBoot + 缓存一致性双写策略 + 延迟双删:先更新 DB 再删缓存,防脏读实战方案

前言 在高并发系统中,缓存是提升性能的重要手段。然而,缓存与数据库之间的一致性问题一直是开发者面临的挑战。当数据发生变化时,如何确保缓存中的数据与数据库中的数据保持一致,是一个需要认真考虑的问题。 想象一下这样的场景:用户A更新了某个商品的价格,系统先更新了数据库,然后删除了缓存。此时,用户B刚好查询该商品的价格,系统发现缓存不存在,于是从数据库读取新价格并写入缓存。这看起来是正常的流程。但如果用户A更新数据时,系统先删除了缓存,然后更新数据库,此时用户B查询时可能会读取到旧数据并写入缓存,导致缓存与数据库不一致。 如何解决这个问题? 本文将详细介绍缓存一致性的双写策略和延迟双删方案,帮助你构建一个可靠的缓存一致性机制。 一、核心概念 1.1 缓存一致性 缓存一致性是指缓存中的数据与数据库中的数据保持一致的状态。在分布式系统中,由于网络延迟、并发操作等因素,缓存与数据库之间可能会出现数据不一致的情况。 1.2 双写策略 双写策略是指在更新数据时,同时更新数据库和缓存。常见的双写策略有两种: 先更新数据库,再更新缓存:这种策略可能会导致数据不一致,因为在更新数据库和更新缓存之间,可能有....

SpringBoot + Redis 大 Key 拆分 + 自动检测告警:单个 Key 超 10MB?自动拆分防阻塞

SpringBoot + Redis 大 Key 拆分 + 自动检测告警:单个 Key 超 10MB?自动拆分防阻塞

前言 在使用 Redis 时,大 Key 是一个常见的性能瓶颈。大 Key 指的是占用内存较大的键值对,通常指单个 Key 大小超过 10MB 的情况。大 Key 会带来一系列问题: 内存占用:大 Key 会占用大量内存,导致内存使用不均衡 网络传输:大 Key 会增加网络传输时间,影响系统响应速度 阻塞操作:对大 Key 进行操作时,会阻塞 Redis 服务器,影响其他操作 过期删除:大 Key 过期时,Redis 会进行同步删除,可能导致服务卡顿 想象一下这样的场景:你的应用在高峰期突然变得响应缓慢,甚至出现服务不可用的情况。通过监控发现,Redis 服务器 CPU 使用率突然飙升,内存使用异常。经过排查,发现是某个 Key 的大小超过了 10MB,导致 Redis 服务器在处理这个 Key 时被阻塞。 如何解决这个问题? 本文将详细介绍如何在 Spring Boot 中实现 Redis 大 Key 的自动检测、拆分和告警,帮助你避免大 Key 带来的性能问题。 一、核心概念 1.1 大 Key 大 Key 是指占用内存较大的键值对,通常有以下几种类型: String 类型:....

Redis扛不住热点Key?SpringBoot自动发现+本地缓存兜底,系统秒级自愈!

Redis扛不住热点Key?SpringBoot自动发现+本地缓存兜底,系统秒级自愈!

一、惊魂5分钟:那个被“爆款商品”打崩的下午 大促当天14:03,监控突然爆红! 🔥 某新款手机开售,商品ID=10086的Key单点QPS冲到12万+ 🔥 Redis CPU瞬间100%,连接池耗尽 🔥 所有服务接口503,客服电话被打爆... 复盘时运维拍桌:“早知道是热点Key,加个本地缓存不就完了?” 可问题来了: ❓ 热点Key谁能提前预知?(昨天卖拖鞋,今天卖火箭) ❓ 手动加缓存?等发现时雪崩已完成 ❓ 加了缓存怎么清理?数据不一致更致命 今天,教你用“自动发现+智能兜底”组合拳 让系统在Redis崩溃前自动防御、秒级自愈,把故障消灭在萌芽!✨ 二、为什么热点Key是“隐形炸弹”? 场景表现后果 爆款商品秒杀单Key QPS 10万+Redis CPU打满,全站瘫痪 明星离婚热搜突发流量涌入连接池耗尽,服务雪崩 恶意爬虫攻击针对性刷某Key资源被耗尽,正常用户无法访问 💡 致命痛点: ❌ 传统方案靠“人肉监控+手动加缓存”,响应速度永远慢半拍 ❌ 固定加本地缓存?99%的Key不需要,浪费内存还引发一致性问题 ✅ 正确姿势:让系统自己“感知热点→自动....

微服务架构下 Spring Session 与 Redis 分布式会话实战全解析

微服务架构下 Spring Session 与 Redis 分布式会话实战全解析

作者:服务端技术精选 标签:Spring Boot · Spring Session · Redis · 微服务 难度:中级 前言 你是否遇到过这样的场景: 用户在服务 A 登录成功,跳转到服务 B 时却提示未登录 多个服务部署在不同服务器,用户刷新页面后 Session 丢失 水平扩展后,新增的服务器无法访问用户 Session 单点登录(SSO)需求,需要跨系统共享登录状态 这些问题在单体应用中不存在,但在微服务架构中却是常见痛点。传统的 HTTP Session 存储在服务器内存中,无法在多个服务之间共享。 今天要介绍的「Spring Session + Redis 分布式会话」方案,将彻底解决这个问题——多服务共享会话,水平扩展无障碍。 一、传统会话的痛点 场景重现 你的系统从单体应用拆分为微服务架构: 单体应用: ┌─────────────────────────────────┐ │ Nginx │ │ ┌───────────────────────┐ │ │ │ 单体应用 │ │ │ │ (Session 存在内存) │ │ │ └─────────────....

SpringBoot + Redis 缓存击穿防护 + 互斥重建:热点 Key 过期时,仅一个线程回源 DB

SpringBoot + Redis 缓存击穿防护 + 互斥重建:热点 Key 过期时,仅一个线程回源 DB

导语 在高并发系统中,缓存是提升性能的关键手段。然而,当热点 Key 过期时,大量并发请求同时穿透缓存直接访问数据库,可能导致数据库压力骤增甚至宕机。这种现象被称为"缓存击穿"。 本文将介绍如何在 SpringBoot 应用中实现 Redis 缓存击穿防护和互斥重建机制,确保热点 Key 过期时,只有一个线程回源数据库,其他线程等待或使用旧数据,从而保护数据库免受高并发冲击。 一、缓存击穿的概念与危害 1.1 什么是缓存击穿 缓存击穿是指某个热点 Key 在高并发访问时突然过期,导致大量并发请求同时穿透缓存直接访问数据库的现象。 场景描述: 某个商品信息被大量用户频繁访问 该商品的缓存 Key 设置了过期时间 缓存过期瞬间,大量请求同时到达 所有请求都发现缓存不存在,同时访问数据库 数据库瞬间承受巨大压力,可能导致宕机 1.2 缓存击穿与相关概念的区别 概念描述解决方案 缓存击穿热点 Key 过期,大量请求同时访问数据库互斥锁、永不过期 缓存穿透查询不存在的数据,请求直接访问数据库布隆过滤器、缓存空值 缓存雪崩大量 Key 同时过期,导致数据库压力骤增过期时间随机化、预热 ....

SpringBoot + Redis 实现登录校验:分布式会话管理,安全又高效

SpringBoot + Redis 实现登录校验:分布式会话管理,安全又高效

一、问题背景:为什么需要 Redis 实现登录校验? 在传统的单体应用中,我们通常使用 Session 来管理用户登录状态。但在微服务架构和分布式系统中,Session 面临着诸多挑战: 传统 Session 的痛点 单点故障:Session 存储在单个服务器上,服务器宕机会导致所有用户登录状态丢失 无法水平扩展:多台服务器之间无法共享 Session,用户请求可能被路由到不同服务器导致登录失效 内存压力:大量用户 Session 占用服务器内存,影响性能 跨域问题:前后端分离架构下,Session 跨域处理复杂 Redis 方案的优势 特性传统 SessionRedis + Token 分布式支持❌ 不支持✅ 天然支持 水平扩展❌ 困难✅ 容易 性能⚠️ 内存受限✅ 独立缓存服务 跨域❌ 复杂✅ 天然支持 安全性⚠️ 一般✅ 可设置过期时间 持久化❌ 易丢失✅ 可持久化 二、核心概念:Token + Redis 认证机制 1. 认证流程 ┌─────────────┐ 1. 登录请求 ┌─────────────┐ │ 客户端 │ ─────────────────&....

SpringBoot + Redis 多级缓存 + L1/L2 自动同步:本地缓存与 Redis 一致性保障

SpringBoot + Redis 多级缓存 + L1/L2 自动同步:本地缓存与 Redis 一致性保障

一、缓存一致性的噩梦 之前参与过一个电商平台,使用了SpringBoot + Redis缓存架构。为了提高性能,在应用层也加入了本地缓存(Caffeine),形成了二级缓存架构: L1缓存:本地缓存(Caffeine),响应速度快 L2缓存:Redis缓存,支持分布式 原本以为这样可以兼顾性能和一致性,但实际运行中却出现了严重的缓存不一致问题。 用户在APP上看到的商品价格和库存信息经常与实际不符,有时候明明已经缺货的商品,页面上还显示有库存,导致用户下单后无法发货,投诉不断。 "我们的缓存更新策略是:修改数据时,先更新数据库,然后删除本地缓存,再删除Redis缓存。但还是会出现不一致的情况。" 这样的场景,作为后端开发的你,是不是也遇到过? 二、多级缓存一致性的挑战 在多级缓存架构中,一致性问题主要来自以下几个方面: 1. 更新顺序问题 如果先更新数据库,再删除缓存,可能会出现: 线程A:读取数据,发现缓存不存在 线程A:从数据库读取数据 线程B:更新数据库 线程B:删除缓存 线程A:将读取到的旧数据写入缓存 结果:缓存中存储的是旧数据 如果先删除缓存,再更新数据库,....

服务端开发博客:后端架构、高并发、性能优化与微服务实战教程