当前位置: 首页 > news >正文

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

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

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

一、缓存雪崩

1.1 什么是缓存雪崩?

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

1.2 缓存雪崩的成因

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

1.3 解决方案

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

1.4 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实现

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等缓存工具
    }
}

三、总结

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


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

相关文章:

  • IDEA 2024.1 最新永久可用(亲测有效)
  • redis序列化设置
  • 使用vscode导出Markdown的PDF无法显示数学公式的问题
  • 【R包】pathlinkR转录组数据分析和可视化利器
  • PyInstaller 打包python 程序 成 可执行文件
  • 算法-数据结构(图)-迪杰斯特拉最短逻辑算法( Dijkstra)
  • 使用扩散模型DDPM生成Sine正弦曲线的案例(使用Classifier-free guidance)
  • 力扣——最长递增子序列
  • (二)未来十至二十年的信息技术核心领域(AI、数据库、编程语言)完全零基础者的学习路径与技能提升策略
  • StableDiffusion打包 项目迁移 项目分发 0
  • DeepSeek如何辅助学术写作的性质研究?
  • 什么是回调函数
  • Linux版本控制器Git【Ubuntu系统】
  • RPA 与 AI 结合:开启智能自动化新时代
  • Wireshark Lua 插件教程
  • window基于wsl部署vllm流程及踩坑经历(包含cuda toolkit、nvcc版本问题)
  • 【leetcode hot 100 15】三数之和
  • StableDiffusion本地部署 2
  • TCP的三次握手与四次挥手:建立与终止连接的关键步骤
  • pta天梯L1-003 个位数统计
  • 美国调整对华加征关税
  • 在古老的意大利科莫歌剧院,廖昌永唱响16首中国艺术歌曲
  • 《克莱默夫妇》导演罗伯特·本顿去世,终年92岁
  • 横跨万里穿越百年,《受到召唤·敦煌》中张艺兴一人分饰两角
  • 宝通科技:与宇树合作已签约,四足机器人在工业场景落地是重点商业化项目
  • 受美关税影响,本田预计新财年净利下降七成,并推迟加拿大建厂计划