网站首页 全球最实用的IT互联网站!

人工智能P2P分享Wind搜索发布信息网站地图标签大全

当前位置:诺佳网 > 软件工程 > 后端开发 > Java >

Redis缓存实战:彻底解决缓存穿透、击穿、雪崩三

时间:2026-03-24 14:45

人气:

作者:admin

标签:

导读:前言 Redis缓存是Java开发中最常用的技术之一,但缓存穿透、击穿、雪崩三大问题也是面试高频考题。本文结合实战代码,带你彻底搞懂这三大难题。 一、缓存穿透 问题描述 查询一个数...

前言

Redis缓存是Java开发中最常用的技术之一,但缓存穿透、击穿、雪崩三大问题也是面试高频考题。本文结合实战代码,带你彻底搞懂这三大难题。

一、缓存穿透

问题描述

查询一个数据库和缓存中都不存在的key,每次请求都打到数据库,大量请求可能拖垃数据库。

解决方案

1. 缓存空对象

@Service
public class UserService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private UserMapper userMapper;

    public User getUserById(Long id) {
        String key = "user:" + id;
        // 查询缓存
        User user = (User) redisTemplate.opsForValue().get(key);
        if (user != null) {
            return user.getId() == null ? null : user; // 返回空对象表示不存在
        }
        // 查询数据库
        user = userMapper.selectById(id);
        if (user == null) {
            // 缓存空对象,设置短过期时间
            redisTemplate.opsForValue().set(key, new User(), 5, TimeUnit.MINUTES);
            return null;
        }
        redisTemplate.opsForValue().set(key, user, 30, TimeUnit.MINUTES);
        return user;
    }
}

2. 布隆过滤器:将所有合法key存入Bloom Filter,请求先过滤器,不存在的key直接拖到。

二、缓存击穿

问题描述

查询一个缓存刚好失效的key,大量请求同时打到数据库。

解决方案

互斥锁(推荐)

public User getUserById(Long id) {
    String key = "user:" + id;
    User user = (User) redisTemplate.opsForValue().get(key);
    if (user != null) return user;

    // 加分布式锁
    String lockKey = "lock:user:" + id;
    Boolean locked = redisTemplate.opsForValue()
        .setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);

    if (Boolean.TRUE.equals(locked)) {
        try {
            // 再次查询缓存(可能其他线程已经写入)
            user = (User) redisTemplate.opsForValue().get(key);
            if (user == null) {
                user = userMapper.selectById(id);
                redisTemplate.opsForValue().set(key, user, 30, TimeUnit.MINUTES);
            }
        } finally {
            redisTemplate.delete(lockKey);
        }
    } else {
        // 未获得锁,稍等重试
        Thread.sleep(50);
        return getUserById(id);
    }
    return user;
}

三、缓存雪崩

问题描述

大量缓存key同时失效,大量请求同时打到数据库。

解决方案

1. 过期时间加随机偶数

// 设置缓存时加随机偶数,避免同时失效
int randomExpire = 30 + new Random().nextInt(10); // 30~40分钟
redisTemplate.opsForValue().set(key, user, randomExpire, TimeUnit.MINUTES);

2. 多级缓存:本地缓存(Caffeine)+ Redis两级,即使 Redis雪崩也有本地缓存托底。

3. 缓存预热:项目启动时提前将热点数据加载到缓存。

总结

问题原因解决方案
缓存穿透 key不存在 空对象 / 布隆过滤器
缓存击穿 key失效瞬间 互斥锁 / 逆机制
缓存雪崩 大量同时失效 随机过期 / 多级缓存

本文由AI辅助创作。

温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信