Redis 缓存穿透介绍

缓存穿透(Cache Penetration)是指客户端请求的数据既不在缓存中,也不在数据库中,导致每次请求都直接访问数据库。这种情况不仅无法发挥缓存的性能优势,还会加重数据库的负担,导致系统性能下降。

缓存穿透的原因

缓存穿透通常有以下几种原因:

  1. 查询的数据不存在:客户端请求的数据在缓存中和数据库中都没有,例如,用户请求的商品或用户数据在系统中根本不存在。
  2. 恶意请求:攻击者故意发送不存在的数据请求,绕过缓存,直接向数据库发起请求。
  3. 缓存未命中数据:由于缓存没有存储数据(可能是由于缓存过期或删除),每次都需要访问数据库。

缓存穿透的影响

  • 增加数据库负载:每次请求都需要访问数据库,即使数据库中没有数据,也会浪费数据库资源,增加数据库的负载。
  • 浪费带宽:客户端无效的请求造成了系统资源的浪费。
  • 性能下降:频繁的缓存穿透会使得缓存的优势无法发挥,系统性能和响应时间会受到影响。

如何解决缓存穿透

  1. 缓存空对象:当查询的结果为空时,可以将空对象缓存,避免相同的无效请求反复查询数据库。
  2. 使用布隆过滤器:布隆过滤器是一种概率型数据结构,适合用来判断某个元素是否在一个集合中。通过使用布隆过滤器,可以在访问缓存之前先进行快速判断,如果请求的数据不在布隆过滤器中,就可以直接拒绝请求,避免不必要的数据库查询。
  3. 请求校验和防火墙:通过验证请求是否合法,限制无效或恶意请求的访问,从而减少无效请求导致的缓存穿透。

Redis 缓存穿透的 Java 实现

1. 使用布隆过滤器防止缓存穿透

布隆过滤器是一种空间效率极高的概率型数据结构,适合用来判断某个元素是否在一个集合中。布隆过滤器能够快速判断某个元素是否存在于数据库中,从而减少不必要的缓存查询。

我们可以通过 Redis 实现布隆过滤器,防止缓存穿透。

步骤:
  1. 安装依赖:使用 Redisson,它是 Redis 的 Java 客户端,支持布隆过滤器功能。
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.16.1</version>
</dependency>

2.代码实现

import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.Redisson;

public class RedisBloomFilterExample {

    // 初始化 Redisson 客户端
    private static RedissonClient redisson;

    public static void main(String[] args) {
        // 配置 Redisson 连接 Redis
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        redisson = Redisson.create(config);

        // 创建布隆过滤器
        RBloomFilter<String> bloomFilter = redisson.getBloomFilter("userExistsFilter");
        
        // 初始化布隆过滤器,预计存储100万个元素,误判率设置为0.03%
        bloomFilter.tryInit(1000000, 0.03);

        // 添加数据到布隆过滤器
        bloomFilter.add("user:1001");
        bloomFilter.add("user:1002");
        bloomFilter.add("user:1003");

        // 模拟检查数据是否存在
        String userId = "user:1001";
        if (bloomFilter.contains(userId)) {
            // 如果布隆过滤器包含该数据,则从缓存获取数据
            System.out.println(userId + " exists in cache.");
        } else {
            // 如果布隆过滤器没有该数据,则查询数据库
            System.out.println(userId + " does not exist in cache, querying database...");
        }

        // 关闭连接
        redisson.shutdown();
    }
}
  1. Redisson 客户端初始化:通过 Redisson.create() 方法初始化客户端连接 Redis。
  2. 创建布隆过滤器:使用 redisson.getBloomFilter() 方法创建布隆过滤器。tryInit 方法用于初始化布隆过滤器的预期容量和误判率。
  3. 添加数据:使用 add() 方法将数据添加到布隆过滤器。
  4. 查询数据:使用 contains() 方法检查数据是否在布隆过滤器中存在。如果存在则从缓存中获取数据,否则查询数据库。

布隆过滤器的优势在于,它能够在大多数情况下快速判断数据是否存在,避免了无效查询数据库的情况。虽然布隆过滤器会存在一定的误判率(可能返回“存在”的错误结果),但它绝对不会漏掉真实存在的数据。

2. 缓存空对象

如果查询到的数据为空,可以将空对象缓存一段时间,避免后续相同的数据查询再次访问数据库。

代码实现
import redis.clients.jedis.Jedis;

public class CacheEmptyObjectExample {

    private static Jedis jedis = new Jedis("localhost", 6379);

    public static void main(String[] args) {
        String key = "user:9999";  // 假设这个用户不存在

        // 尝试从缓存获取数据
        String value = getFromCache(key);

        if (value == null) {
            // 如果缓存中没有,查询数据库
            value = getFromDatabase(key);

            // 如果数据库中没有数据,缓存一个空值(避免下次重复查询)
            if (value == null) {
                setToCache(key, "null");
            } else {
                setToCache(key, value);
            }
        }

        System.out.println("Fetched value: " + value);
    }

    // 从缓存获取数据
    public static String getFromCache(String key) {
        return jedis.get(key);
    }

    // 设置数据到缓存
    public static void setToCache(String key, String value) {
        jedis.setex(key, 3600, value);  // 设置 1 小时过期时间
    }

    // 模拟数据库查询
    public static String getFromDatabase(String key) {
        // 假设数据库中没有这个数据
        return null;
    }
}
代码解析
  1. 查询缓存:首先从 Redis 获取缓存,如果返回为 null,则说明缓存中没有数据。
  2. 查询数据库:如果 Redis 缓存没有数据,则从数据库查询。
  3. 缓存空值:如果数据库查询结果为空(如用户不存在),则将 "null" 存入 Redis 中,表示该数据不存在。这样可以避免频繁访问数据库,提高性能。
  4. 缓存设置过期时间:使用 setex 设置缓存的过期时间(如 1 小时)。
全部评论

相关推荐

2024-12-29 15:37
已编辑
西华大学 图像识别
程序员牛肉:去不了,大厂算法卡学历吧
点赞 评论 收藏
分享
2024-12-22 19:38
已编辑
黄冈师范学院 后端
寿命齿轮:实习就一段还拉了,项目一看就不是手搓,学历也拉了,技术栈看着倒是挺好,就是不知道面试表现能咋样。 不过现在才大三,争取搞两端大厂实习,或者一个纯个人项目+一段大厂,感觉秋招还是未来可期。
投递美团等公司8个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务