Redis中使用布隆过滤器解决缓存穿透问题

一、缓存穿透(失效)问题

缓存穿透是指查询一个一定不存在的数据,由于缓存中没有命中,会去数据库中查询,而数据库中也没有该数据,并且每次查询都不会命中缓存,从而每次请求都直接打到了数据库上,这会给数据库带来巨大压力。

二、布隆过滤器原理

布隆过滤器(Bloom Filter)是一种空间效率很高的随机数据结构,它利用多个不同的哈希函数将一个元素映射到一个位数组中的多个位置,并将这些位置的值置为 1。

当查询一个元素时,同样使用这些哈希函数计算出多个位置,如果这些位置上的值都为 1,那么这个元素可能存在;如果有任何一个位置上的值为 0,那么这个元素一定不存在。

布隆过滤器存在一定的误判概率,即可能会把不存在的元素判断为存在,但不会把存在的元素判断为不存在。

三、使用 Redis 中的布隆过滤器解决缓存穿透问题的代码

  1. 引入依赖
xml 复制代码
<dependency>
       <groupId>org.redisson</groupId>
       <artifactId>redisson</artifactId>
       <version>3.21.1</version>
   </dependency>
  1. 代码实现
java 复制代码
import org.redisson.Redisson;
   import org.redisson.api.RBloomFilter;
   import org.redisson.api.RedissonClient;

   public class BloomFilterCache {
       private final RedissonClient redissonClient;
       private final RBloomFilter<String> bloomFilter;

       public BloomFilterCache() {
           redissonClient = Redisson.create();
           // 创建布隆过滤器,预计插入 10000 个元素,误判率为 0.01
           bloomFilter = redissonClient.getBloomFilter("myBloomFilter");
           bloomFilter.tryInit(10000, 0.01);
       }

       public boolean mightContain(String key) {
           return bloomFilter.contains(key);
       }

       public void add(String key) {
           bloomFilter.add(key);
       }

       public void close() {
           redissonClient.shutdown();
       }

       public static void main(String[] args) {
           BloomFilterCache bloomFilterCache = new BloomFilterCache();

           // 添加一些可能存在的键
           bloomFilterCache.add("key1");
           bloomFilterCache.add("key2");

           // 查询键是否可能存在
           System.out.println(bloomFilterCache.mightContain("key1")); // true
           System.out.println(bloomFilterCache.mightContain("key3")); // false

           bloomFilterCache.close();
       }
   }

在上述代码中,首先创建了一个 Redisson 客户端,并初始化了一个布隆过滤器。mightContain方法用于判断一个键是否可能存在于布隆过滤器中,add方法用于向布隆过滤器中添加一个键。

使用布隆过滤器可以在缓存之前进行快速判断,减少对数据库的不必要查询,从而有效地解决缓存穿透问题。

获取到缓存失效后改怎么处理?

  1. 返回异常信息,业务流程往下走
  2. 记录对应的日志信息
  3. 异步缓存key到redis
    1. 当使用布隆过滤器判断某个 key 不存在时,触发一个异步任务。
    2. 异步任务从可能的数据来源(如数据库、外部 API 等)获取该 key 对应的数据。
    3. 如果获取到数据,将其存入缓存(Redis 或其他缓存系统),以便下次查询时能够快速响应。
相关推荐
麦聪聊数据17 分钟前
Web 原生架构如何重塑企业级数据库协作流?
数据库·sql·低代码·架构
未来之窗软件服务17 分钟前
数据库优化提速(四)新加坡房产系统开发数据库表结构—仙盟创梦IDE
数据库·数据库优化·计算机软考
时艰.1 小时前
Java 并发编程 — 并发容器 + CPU 缓存 + Disruptor
java·开发语言·缓存
Goat恶霸詹姆斯2 小时前
mysql常用语句
数据库·mysql·oracle
大模型玩家七七2 小时前
梯度累积真的省显存吗?它换走的是什么成本
java·javascript·数据库·人工智能·深度学习
曾经的三心草2 小时前
redis-9-哨兵
数据库·redis·bootstrap
明哥说编程2 小时前
Dataverse自定义表查询优化:D365集成大数据量提速实战【索引配置】
数据库·查询优化·dataverse·dataverse自定义表·索引配置·d365集成·大数据量提速
张小凡vip2 小时前
Kubernetes--k8s中部署redis数据库服务
redis·kubernetes
xiaowu0802 小时前
C# 拆解 “显式接口实现 + 子类强类型扩展” 的设计思想
数据库·oracle
讯方洋哥3 小时前
HarmonyOS App开发——关系型数据库应用App开发
数据库·harmonyos