«

Redis 缓存穿透解决

时间:2026-10-9 07:36     作者:emer     分类: 无


Redis 缓存穿透解决

缓存穿透是常见问题,恶意请求能把数据库打挂。

1. 什么是缓存穿透

现象: 请求的数据在缓存和数据库中都不存在,每次请求都直接打到数据库。

危害:

2. 为什么会穿透

3. 解决方案一:缓存空值

思路: 即使数据库查不到,也在Redis存一个空值,设置短过期时间。

function getUser($id) {
    $key = "user:$id";
    $user = $redis->get($key);

    if ($user !== false) {
        // 空值标记
        if ($user === 'null') {
            return null;
        }
        return json_decode($user, true);
    }

    // 查数据库
    $user = $db->query("SELECT * FROM users WHERE id = $id");

    if ($user) {
        // 存在就缓存1小时
        $redis->setex($key, 3600, json_encode($user));
    } else {
        // 不存在也缓存,5分钟过期
        $redis->setex($key, 300, 'null');
    }

    return $user;
}

优点: 简单有效
缺点: 占内存,可能被恶意key刷爆

4. 解决方案二:布隆过滤器

思路: 在缓存前面加一层布隆过滤器,不存在的key直接拦截。

原理:

PHP 示例(用 Redis 的布隆过滤器模块):

# 加载 RedisBloom 模块
redis-cli BF.ADD user:1
redis-cli BF.EXISTS user:1
function getUser($id) {
    $key = "user:$id";

    // 先过布隆过滤器
    if (!$redis->rawCommand('BF.EXISTS', 'user_filter', $id)) {
        return null; // 一定不存在
    }

    // 布隆说可能存在,再查缓存
    $user = $redis->get($key);
    if ($user) {
        return json_decode($user, true);
    }

    // 查数据库...
}

优点: 内存占用小,效率高
缺点: 有误判率,实现复杂

5. 解决方案三:参数校验

思路: 从源头过滤非法请求。

function getUser($id) {
    // 参数校验
    if ($id <= 0 || !is_numeric($id)) {
        return null;
    }

    // 正常查询逻辑...
}

适用: ID类查询,不合法直接拦截

6. 三种方案对比

方案 优点 缺点 适用场景
缓存空值 简单 占内存 数据量不大
布隆过滤器 高效 误判,复杂 数据量大
参数校验 最直接 只防非法 ID类请求

7. 生产建议

1)组合使用

2)空值过期时间要短

3)监控异常请求

4)接口限流

8. 缓存雪崩和击穿

缓存穿透: 查不存在的数据
缓存击穿: 热点key过期,大量请求打数据库
缓存雪崩: 大量key同时过期

区分清楚: 三个问题现象类似但原因不同,解决方案也不同。

总结

Redis 缓存穿透解决要点:

缓存穿透是面试高频题,也是生产常见问题,一定要掌握。

标签: 数据库 Redis 缓存穿透 布隆过滤器 缓存优化