news 2026/9/8 15:45:18

说说什么是Redis缓存击穿、缓存穿透、缓存雪崩?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
说说什么是Redis缓存击穿、缓存穿透、缓存雪崩?

大家好,我是锋哥。最近不少粉丝问锋哥什么是Redis缓存击穿、缓存穿透、缓存雪崩?今天锋哥来总结下,大家可以参考。

2026年,锋哥又开始收Java学员了!

Redis作为高性能的键值存储解决方案,广泛应用于缓存机制中。然而,在其实际使用中,开发者们常常会遇到“缓存击穿”、“缓存穿透”和“缓存雪崩”这几个概念。为了解释这些问题,并提供相应的解决方案,本文将结合Java代码进行说明。

一、缓存击穿

定义

缓存击穿是指在高并发情况下,某个热点数据的缓存失效,导致大量请求同时访问数据库,从而对数据库造成巨大的压力。

场景

假设某个用户的数据在缓存中失效,且每个请求同时访问数据库,数据库可能因此崩溃。

解决方案

使用互斥锁(例如,用Redis的SETNX命令),确保只有一个请求去查询数据库。

Java代码示例
import redis.clients.jedis.Jedis;public class CacheTest {private Jedis jedis = new Jedis("localhost");public String getData(String key) {String data = jedis.get(key);if (data == null) {// 使用分布式锁String lockKey = "lock:" + key;String lockValue = String.valueOf(System.currentTimeMillis() + 10000); // 10秒锁if (jedis.setnx(lockKey, lockValue) == 1) {try {// 此处模拟数据库查询data = queryDatabase(key);jedis.set(key, data);} finally {jedis.del(lockKey); // 释放锁}} else {// 等待一段时间后重试Thread.sleep(100);return getData(key);}}return data;}private String queryDatabase(String key) {// 模拟数据库查询return "data_for_" + key; // 返回数据库中的数据}}

二、缓存穿透

定义

缓存穿透指的是请求的数据在缓存和数据库中均不存在,导致每次请求都直达数据库,造成数据库的负担。

场景

攻击者可能发送大量请求,访问不存在的ID,导致数据库处理大量无效请求。

解决方案

引入布隆过滤器,提前过滤不存在的请求,或者对不存在的数据进行空对象缓存。

Java代码示例
import redis.clients.jedis.Jedis;public class CacheTest {private Jedis jedis = new Jedis("localhost");public String getData(String key) {// 布隆过滤器模拟if (!isKeyValid(key)) {return null; // 过滤掉无效请求}String data = jedis.get(key);if (data == null) {// 查询数据库data = queryDatabase(key);if (data == null) {// 将空对象缓存jedis.set("empty:" + key, ""); // 设置空对象缓存} else {jedis.set(key, data);}}return data;}private boolean isKeyValid(String key) {// 模拟布隆过滤器的有效性判断return key.matches("^[a-zA-Z0-9]+$"); // 仅允许字母和数字}private String queryDatabase(String key) {// 模拟数据库查询return "data_for_" + key; // 返回数据库中的数据}}

三、缓存雪崩

定义

缓存雪崩是指在某个时间点,大量缓存数据同时失效,导致缓存不可用,所有请求直达数据库。

场景

例如,若多个缓存的过期时间设定为相同,到了同一时刻,所有缓存都失效,直接向数据库发送请求。

解决方案

设置不同的过期时间,避免同时失效。

Java代码示例
import redis.clients.jedis.Jedis;public class CacheTest {private Jedis jedis = new Jedis("localhost");public String getData(String key) {String data = jedis.get(key);if (data == null) {// 查询数据库data = queryDatabase(key);if (data != null) {// 设置不同过期时间,使用随机时间int randomExpireTime = 60 + (int)(Math.random() * 60); // 随机60秒到120秒jedis.setex(key, randomExpireTime, data); // 设置过期时间}}return data;}private String queryDatabase(String key) {// 模拟数据库查询return "data_for_" + key; // 返回数据库中的数据}}

最后总结下,Redis在缓存中能够有效提升系统性能,但在实际应用中,缓存击穿、缓存穿透和缓存雪崩是不可忽视的问题。通过上述的示例和解决方案,开发者可以基于Java和Redis构建更加稳定和高效的缓存机制,提高系统的可靠性和响应速度。希望本篇文章能为大家提供帮助和启发。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 14:27:58

【C#与.NET 9新特性深度预览】:抢先掌握2024年最值得关注的5大变革

第一章:C#与.NET 9新特性全景概览 随着 .NET 9 的正式发布,微软在性能优化、语言表达力和开发体验方面带来了多项突破性更新。本章将全面介绍 C# 13 与 .NET 9 框架中的核心新特性,帮助开发者快速掌握下一代 .NET 技术栈的关键能力。 更简洁…

作者头像 李华
网站建设 2026/9/8 14:05:03

Boost.thread即将被淘汰?,新一代C++协程与Boost融合技术前瞻

第一章&#xff1a;Boost.thread的现状与挑战 Boost.Thread 是 Boost C 库中用于支持多线程编程的核心组件之一&#xff0c;长期以来为开发者提供了跨平台的线程管理能力。尽管其接口设计优雅且功能强大&#xff0c;但随着 C11 标准引入原生的 <thread> 支持&#xff0c…

作者头像 李华
网站建设 2026/8/30 9:47:42

C++模板类声明与实现分离:为什么你的代码无法通过编译?

第一章&#xff1a;C模板类声明与实现分离的编译之谜 C模板的实例化机制决定了其声明与实现无法像普通函数那样自然分离。当编译器遇到模板类的声明&#xff08;如在头文件中&#xff09;而未见其实现时&#xff0c;它无法生成具体类型的代码——因为模板本身不是真实类型&…

作者头像 李华
网站建设 2026/9/4 1:19:13

低成本GPU部署fft npainting lama:图像修复系统降本50%方案

低成本GPU部署fft npainting lama&#xff1a;图像修复系统降本50%方案 1. 引言&#xff1a;为什么需要更高效的图像修复方案&#xff1f; 你有没有遇到过这样的情况&#xff1a;客户发来一张带水印的宣传图&#xff0c;你想去掉水印重新使用&#xff0c;但PS手动修复太耗时间…

作者头像 李华
网站建设 2026/9/2 13:11:14

【安全编码实战】:从strcat到strlcat、snprintf的迁移策略详解

第一章&#xff1a;C语言字符串拼接的安全隐患概述 在C语言中&#xff0c;字符串本质上是字符数组&#xff0c;缺乏现代编程语言中的安全边界检查机制。因此&#xff0c;在进行字符串拼接操作时&#xff0c;极易引发缓冲区溢出等严重安全问题。这类漏洞不仅可能导致程序崩溃&am…

作者头像 李华