【缓存】缓存雪崩与缓存穿透:高并发系统的隐形杀手

缓存雪崩与缓存穿透:高并发系统的隐形杀手

在高并发系统中,缓存是提升性能的重要手段。然而,缓存使用不当也会带来一系列问题,其中最常见的就是缓存雪崩缓存穿透。这两个问题如果不加以解决,可能会导致系统崩溃,甚至引发严重的生产事故。本文将深入探讨缓存雪崩和缓存穿透的成因,并提供解决方案,最后用Java代码实现。

一、缓存雪崩

1.1 什么是缓存雪崩?

缓存雪崩是指大量缓存数据在同一时间失效,导致所有请求都直接打到数据库上,数据库瞬间承受巨大压力,甚至崩溃。

1.2 缓存雪崩的成因

  • 缓存集中过期:缓存数据设置了相同的过期时间,导致大量缓存同时失效。
  • 缓存服务器宕机:缓存服务器出现故障,无法提供服务。

1.3 解决方案

  1. 设置不同的过期时间:为缓存数据设置随机的过期时间,避免同时失效。
  2. 使用多级缓存:在本地缓存和分布式缓存之间增加一层缓存,减少直接访问数据库的压力。
  3. 缓存预热:在系统启动时,提前加载热点数据到缓存中。
  4. 限流降级:使用限流工具(如Sentinel)对数据库进行保护,防止数据库被压垮。

1.4 Java实现

java 复制代码
import java.util.Random;
import java.util.concurrent.TimeUnit;

public class CacheAvalancheSolution {

    private static final int BASE_EXPIRE_TIME = 3600; // 基础过期时间
    private static final int RANDOM_RANGE = 600; // 随机范围

    public static void main(String[] args) {
        // 模拟缓存数据
        String cacheKey = "hot_data";
        String cacheValue = getDataFromCache(cacheKey);

        if (cacheValue == null) {
            // 缓存失效,重新加载
            cacheValue = getDataFromDB();
            setCacheWithRandomExpire(cacheKey, cacheValue);
        }

        System.out.println("Cache Value: " + cacheValue);
    }

    private static String getDataFromCache(String key) {
        // 模拟从缓存中获取数据
        return null; // 假设缓存失效
    }

    private static String getDataFromDB() {
        // 模拟从数据库中获取数据
        return "Data from DB";
    }

    private static void setCacheWithRandomExpire(String key, String value) {
        // 设置缓存,并添加随机过期时间
        int expireTime = BASE_EXPIRE_TIME + new Random().nextInt(RANDOM_RANGE);
        System.out.println("Set cache with expire time: " + expireTime + " seconds");
        // 实际项目中可以使用Redis等缓存工具
    }
}

二、缓存穿透

2.1 什么是缓存穿透?

缓存穿透是指查询一个不存在的数据,由于缓存中没有该数据,请求直接打到数据库上。如果大量请求查询不存在的数据,数据库可能会被压垮。

2.2 缓存穿透的成因

  • 恶意攻击:攻击者故意查询不存在的数据,导致数据库压力过大。
  • 业务逻辑问题:业务代码中没有对查询参数进行校验,导致大量无效查询。

2.3 解决方案

  1. 布隆过滤器:使用布隆过滤器过滤掉不存在的数据,避免无效查询。
  2. 缓存空值:对于查询结果为空的请求,缓存一个空值,并设置较短的过期时间。
  3. 参数校验:在业务逻辑层面对查询参数进行校验,过滤掉无效请求。

2.4 Java实现

java 复制代码
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;

public class CachePenetrationSolution {

    private static BloomFilter<String> bloomFilter = BloomFilter.create(
            Funnels.stringFunnel(), 1000000, 0.01); // 布隆过滤器

    public static void main(String[] args) {
        // 模拟查询
        String queryKey = "non_existent_key";

        if (!bloomFilter.mightContain(queryKey)) {
            // 布隆过滤器判断不存在
            System.out.println("Data not exist in bloom filter");
            return;
        }

        String cacheValue = getDataFromCache(queryKey);
        if (cacheValue == null) {
            // 缓存失效,重新加载
            cacheValue = getDataFromDB(queryKey);
            if (cacheValue == null) {
                // 数据库中没有该数据,缓存空值
                setCacheWithShortExpire(queryKey, "NULL");
            } else {
                setCacheWithShortExpire(queryKey, cacheValue);
            }
        }

        System.out.println("Cache Value: " + cacheValue);
    }

    private static String getDataFromCache(String key) {
        // 模拟从缓存中获取数据
        return null; // 假设缓存失效
    }

    private static String getDataFromDB(String key) {
        // 模拟从数据库中获取数据
        return null; // 假设数据库中不存在该数据
    }

    private static void setCacheWithShortExpire(String key, String value) {
        // 设置缓存,并添加较短的过期时间
        System.out.println("Set cache with short expire time for key: " + key);
        // 实际项目中可以使用Redis等缓存工具
    }
}

三、总结

缓存雪崩和缓存穿透是高并发系统中常见的缓存问题,如果不加以解决,可能会导致系统崩溃。通过设置不同的过期时间、使用布隆过滤器、缓存空值等方法,可以有效避免这些问题。在实际项目中,我们需要根据业务场景选择合适的解决方案,确保系统的稳定性和高性能。


关注我,获取更多技术干货!如果你有任何问题或建议,欢迎在评论区留言。

相关推荐
2301_793086871 小时前
Redis 04 Reactor
数据库·redis·缓存
189228048615 小时前
NY243NY253美光固态闪存NY257NY260
大数据·网络·人工智能·缓存
青鱼入云6 小时前
redis怎么做rehash的
redis·缓存
FFF-X6 小时前
Vue3 路由缓存实战:从基础到进阶的完整指南
vue.js·spring boot·缓存
夜影风1 天前
Nginx反向代理与缓存实现
运维·nginx·缓存
编程(变成)小辣鸡1 天前
Redis 知识点与应用场景
数据库·redis·缓存
菜菜子爱学习2 天前
Nginx学习笔记(八)—— Nginx缓存集成
笔记·学习·nginx·缓存·运维开发
魏波.2 天前
常用缓存软件分类及详解
缓存
yh云想2 天前
《多级缓存架构设计与实现全解析》
缓存·junit
白仑色2 天前
Redis 如何保证数据安全?
数据库·redis·缓存·集群·主从复制·哨兵·redis 管理工具