redis实战-缓存穿透、缓存击穿、缓存雪崩

简介: redis实战-缓存穿透、缓存击穿、缓存雪崩

缓存穿透、击穿、雪崩

6.3 后记


一:故事背景

使用Redis进行缓存,我们就必须要知道使用Redis可能会出现的问题,只有这样,我们再能更好规避,更好的使用Redis,为我们服务。

今天我们就来讲讲Redis的经典问题,Redis缓存的穿透、击穿、雪崩。

二:业务场景


2.1 业务场景

我们假设一个简单的业务场景,有一个在线商城系统


用户可以根据商品ID查询商品信息。系统使用Redis作为缓存,将商品信息存储在缓存中,键的格式为"product:{productId}",值为商品的详细信息。

当用户请求查询商品信息时,首先尝试从Redis缓存中获取,如果缓存中不存在,则从数据库中查询,并将查询结果存储到缓存中。

2.2代码实现

@Service
public class ProductService {
    @Autowired
    private RedisTemplate<String, Product> redisTemplate;
    public Product getProductInfo(String productId) {
        // 尝试从缓存中获取商品信息
        Product product = redisTemplate.opsForValue().get("product:" + productId);
        if (product == null) {
            // 如果缓存中不存在,则从数据库查询
            product = queryProductInfoFromDatabase(productId);
            if (product == null) {
                // 如果查询结果为空,将空值存储到缓存中,并设置较短的过期时间
                redisTemplate.opsForValue().set("product:" + productId, null, 300, TimeUnit.SECONDS);
            } else {
                // 将查询结果存储到缓存中
                redisTemplate.opsForValue().set("product:" + productId, product);
            }
        }
        return product;
    }
    private Product queryProductInfoFromDatabase(String productId) {
        // 从数据库查询商品信息
        // ...
    }
}

上述代码给出了,我们所述业务场景的实现。接下来我们就结合这个场景分别解释,缓存穿透、缓存击穿、缓存雪崩。


三:缓存穿透

3.1 什么是缓存穿透

缓存穿透指的是在缓存中无法找到需要的数据,导致每次请求都需要访问底层数据存储,从而引发数据库负载过大的情况。通常发生在恶意请求或者查询不存在的数据时。


3.2 解决方案

3.2.1 缓存空值

在缓存中存储空值,并且设置一个较短的过期时间,防止频繁的查询请求,直接访问数据库。上面的代码里也编写了此部分代码

if (product == null) {
    // 如果查询结果为空,将空值存储到缓存中,并设置较短的过期时间
    redisTemplate.opsForValue().set("product:" + productId, null, 300, TimeUnit.SECONDS);
    }

3.2.2 数据预热

在系统启动时,可以将热门或者常用的数据预先加载到缓存中,从而避免冷启动时大量的缓存穿透请求。比如可以使用定时任务进数据预热。

// 在系统启动时加载热门数据到缓存中
@PostConstruct
public void initCache() {
    // 查询热门数据
    List<Product> hotProducts = queryHotProductsFromDatabase();
    // 将热门数据放入缓存
    for (Product product : hotProducts) {
        redisTemplate.opsForValue().set("product:" + product.getId(), product, 5, TimeUnit.MINUTES);
    }
}

3.2.3 数据库优化查询

可以通过对数据库的查询进行优化,例如使用索引、缓存数据库查询结果等方式,从而减少数据库查询的耗时,降低数据库负载,减少缓存穿透的发生。

这个方法并未解决穿透问题,只是从数据库层面降低了缓存穿透带来的问题。


四:缓存击穿

4.1什么是缓存击穿

缓存击穿指的是一个原本存在于缓存中的数据过期或者被删除,而此时恰好有大量的请求同时访问这个数据,导致这些请求都无法从缓存中获取数据,而需要访问底层数据存储,从而引发数据库负载过大的情况。


4.2解决方案

4.2.1 加锁防止并发访问数据库。

在缓存失效时,通过加锁来保证只有一个请求可以访问数据库,其他请求等待并共享查询结果。分布式锁可以看我的这篇博客redis分布式锁


五:缓存雪崩

5.1 什么是缓存雪崩

缓存雪崩指的是在缓存中大量的数据同时过期或失效,导致多个请求同时访问底层数据存储,从而引发数据库负载过大的情况。


5.2解决方案

5.2.1 设置合适的缓存过期时间

合理设置缓存的过期时间,避免大量缓存在同一时间内失效,从而降低缓存雪崩的风险。可以通过设置不同的过期时间,将缓存的过期时间分散开来,避免同时失效。

 if (product != null) {
                // 将查询结果存储到缓存中,并设置随机的过期时间,范围为 1~5 分钟
                int expireTime = new Random().nextInt(5) + 1;
                redisTemplate.opsForValue().set("product:" + productId, product, expireTime, TimeUnit.MINUTES);
            }

5.2.2 引入多级缓存

通过在缓存系统中引入多层级的缓存,例如一级缓存(内存缓存)和二级缓存(分布式缓存如Redis),可以在一级缓存失效时,从二级缓存获取数据,并在二级缓存中更新一级缓存,从而减少直接请求后端系统的次数。


5.2.3 限流和熔断

在缓存失效时,可以考虑限流和熔断策略,防止大量请求涌入后端系统,可以通过设置请求的并发数限制、请求频率限制等方式控制请求的流量,保护后端系统的稳定性。


六:总结&提升

6.1 总结

缓存穿透、缓存击穿和缓存雪崩是常见的缓存使用问题,可能导致系统性能下降甚至系统崩溃。

使用合适的缓存策略,如设置合理的缓存过期时间、使用分布式缓存等,可以有效避免这些问题的发生。

6.2 提升

在使用Spring Boot和Redis进行缓存时,可以通过合理地配置缓存的过期时间、使用缓存的自动刷新功能、合理设计缓存的Key和Value结构等方式来避免这些问题的发生,从而提高系统的性能和稳定性。

6.3 后记

通过此篇文章相信你对Redis的缓存穿透、击穿、雪崩、有了一定的了解,还在等什么,赶紧实践起来吧。


目录
相关文章
|
缓存 数据库连接 数据库
缓存三剑客(穿透、击穿、雪崩)
缓存穿透指查询数据库和缓存中都不存在的数据,导致请求直接冲击数据库。解决方案包括缓存空对象和布隆过滤器。缓存击穿是大量请求访问同一个失效的热点数据,使数据库瞬间压力剧增,解决方法有提前预热、设置永不过期、加锁限流等。缓存雪崩是大量key同时失效,导致所有请求直达数据库,可通过引入随机过期时间缓解。三者分别对应单点爆破、全面崩塌等问题,需根据场景选择合适策略优化系统性能与稳定性。
700 0
|
存储 缓存 NoSQL
如何解决缓存击穿?
缓存击穿是指热点数据失效时大量请求直接冲击数据库,可能导致系统崩溃。解决方案包括:永不过期策略避免缓存失效瞬间的穿透;互斥锁控制并发访问;热点预热提前刷新缓存;熔断降级在数据库压力大时返回默认值;二级缓存降低Redis压力。实际中常组合使用多种方案,如热点预热+互斥锁+熔断降级,以提升系统稳定性与性能。
1469 0
|
10月前
|
缓存 负载均衡 监控
135_负载均衡:Redis缓存 - 提高缓存命中率的配置与最佳实践
在现代大型语言模型(LLM)部署架构中,缓存系统扮演着至关重要的角色。随着LLM应用规模的不断扩大和用户需求的持续增长,如何构建高效、可靠的缓存架构成为系统性能优化的核心挑战。Redis作为业界领先的内存数据库,因其高性能、丰富的数据结构和灵活的配置选项,已成为LLM部署中首选的缓存解决方案。
939 25
|
11月前
|
存储 缓存 NoSQL
Redis专题-实战篇二-商户查询缓存
本文介绍了缓存的基本概念、应用场景及实现方式,涵盖Redis缓存设计、缓存更新策略、缓存穿透问题及其解决方案。重点讲解了缓存空对象与布隆过滤器的使用,并通过代码示例演示了商铺查询的缓存优化实践。
426 1
Redis专题-实战篇二-商户查询缓存
|
10月前
|
缓存 并行计算 监控
vLLM 性能优化实战:批处理、量化与缓存配置方案
本文深入解析vLLM高性能部署实践,揭秘如何通过continuous batching、PagedAttention与前缀缓存提升吞吐;详解批处理、量化、并发参数调优,助力实现高TPS与低延迟平衡,真正发挥vLLM生产级潜力。
2564 0
vLLM 性能优化实战:批处理、量化与缓存配置方案
|
10月前
|
缓存 运维 监控
Redis 7.0 高性能缓存架构设计与优化
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Redis 7.0高性能缓存架构,探索函数化编程、多层缓存、集群优化与分片消息系统,用代码在二进制星河中谱写极客诗篇。
1855 3
|
11月前
|
缓存 NoSQL 关系型数据库
Redis缓存和分布式锁
Redis 是一种高性能的键值存储系统,广泛用于缓存、消息队列和内存数据库。其典型应用包括缓解关系型数据库压力,通过缓存热点数据提高查询效率,支持高并发访问。此外,Redis 还可用于实现分布式锁,解决分布式系统中的资源竞争问题。文章还探讨了缓存的更新策略、缓存穿透与雪崩的解决方案,以及 Redlock 算法等关键技术。
|
缓存 监控 安全
告别缓存击穿!Go 语言中的防并发神器:singleflight 包深度解析
在高并发场景中,多个请求同时访问同一资源易导致缓存击穿、数据库压力过大。Go 语言提供的 `singleflight` 包可将相同 key 的请求合并,仅执行一次实际操作,其余请求共享结果,有效降低系统负载。本文详解其原理、实现及典型应用场景,并附示例代码,助你掌握高并发优化技巧。
829 0
|
存储 缓存 安全
Go语言实战案例-LRU缓存机制模拟
本文介绍了使用Go语言实现LRU缓存机制的方法。LRU(最近最少使用)是一种常见缓存淘汰策略,当缓存满时,优先删除最近最少使用的数据。实现中使用哈希表和双向链表结合的方式,确保Get和Put操作均在O(1)时间内完成。适用于Web缓存、数据库查询优化等场景。
|
缓存 NoSQL 数据库
什么是缓存击穿
缓存击穿是指热点缓存key突然失效,导致大量并发请求直接冲击数据库,造成巨大压力。常见于高并发场景,如热门商品信息失效时。解决方法包括设置热点key永不过期、使用分布式锁、预热数据、熔断降级等,以保障系统稳定性。
1073 0