redis布隆过滤器与四个缓存问题
创始人
2024-06-01 10:44:47
0

目录

    • 布隆过滤器
        • 定义
        • 特性
        • 使用场景
          • 解决缓存穿透的问题
          • 黑白名单校验
        • 底层原理
          • 哈希冲突案例
          • 添加key
          • 查询key
        • 总结
    • 四个缓存问题
      • 缓存雪崩
        • 定义
        • 解决方案
      • 缓存穿透
        • 定义
        • 解决方案
        • 方案一
        • 方案二(guava实现)
          • 代码案例
          • 源码分析
        • 方案三(RedisSon实现)
            • 代码实现
        • 方案四(直接安装redis插件,应用层解决方案)
          • 编译安装Rebloom插件
          • docker安装
      • 缓存击穿
        • 定义
        • 解决方案

布隆过滤器

定义

它实际上是一个很长的二进制数组+一系列随机hash算法映射函数,主要用于快速的判断一个元素是否在集合中.
布隆过滤器的初始状态

他的判断结果并不是百分之百准确的

特性

  • 高效的插入和查询,占用空间少,返回的结果是不确定性的
  • 一个元素如果判断结果为存在的时候元素不一定存在,但是判断结果为不存在的时候则一定不存在
  • 布隆过滤器可以添加元素,但是不能删除元素.因为删除元素会导致误判率增加
  • 误判只会发生在过滤器没有添加过的元素,对于已经添加过的元素不会发生误判.

因为可能发生hash冲突

使用场景

解决缓存穿透的问题

把已经存在数据的key存放到布隆过滤器中,相当于在redis前面再加一层拦截过滤.
当有新的请求时,先到布隆过滤器中查询是否存在,如果布隆过滤器不存在该条数据则直接返回,如果布隆过滤器中已存在,才去查询redis缓存,如果redis没有再去查询mysql

黑白名单校验

直接判断值在不在布隆过滤器里面

底层原理

哈希冲突案例
public static void main(String[] args) {System.out.println("Aa".hashCode());System.out.println("BB".hashCode());}
添加key

使用多个hash函数对key进行hash运算得到一个整数索引值,对位数组长度进行取模运算得到一个位置,每个hash函数都会得到一个不同的位置,将这几个位置都置为1就完成了add操作
添加key的图示
添加n个key
添加一个key

查询key

只要有其中一位是0就表示这个key不存在,如果都是1(都是布隆过滤器就返回存在),但是不一定就代表存在这对应的key.
因为只要是hash函数就存在hash冲突,哪怕是采用了多个hash函数也有可能会跟其他的多个key值hash出来的值冲突,所以不能确定一定存在
查询误判示意图:
查询误判示意图

总结

  • 有是有可能有,无就是一定无
  • 使用时最好不要让实际元素数量远大于初始化数量
  • 当实际元素数量超过初始化数量时,应该对布隆过滤器进行重建,重新分配一个size更大的过滤器,再将所有的历史元素批量add进去
  • 优点
  • 高效的插入和查询
  • 占用空间很少
  • 缺点
  • 不能删除元素(因为删除元素会导致误判率的增加,因为hash冲突同一个槽位对应多个对象的信息,你删除一个元素很可能把其他的也删除了)
  • 存在误判率(hash冲突,不同的数据对象可能会出来相同的hash值)

四个缓存问题

缓存雪崩

定义

redis主机挂了,redis全盘崩溃(或者缓存中有大量数据同时过期)

解决方案

  • redis缓存集群实现高可用
    • 主从+哨兵
    • Redis Cluster
  • ehcache本地缓存 + Hystrix或者阿里sentinel限流降级
  • 开启redis持久化机制aof/rdb,尽快恢复缓存集群

缓存穿透

定义

一般情况下,先查询缓存redis是否有该条数据,缓存未命中时,在查询数据库.当数据库也不存在该条数据时,每次查询都要访问数据库,这就是缓存穿透.它带来的问题就是当有大量的请求查询数据库本身就不存在的数据时,就会给数据库带来压力,甚至是直接拖垮数据库

解决方案

  • 方案1:空对象缓存或者缺省值
  • 方案2:google布隆过滤器guava解决缓存穿透
  • 方案3:redis布隆过滤器解决缓存穿透

方案一

就是缓存一个空值或者业务上定义的缺省值在redis里面缓存返回(每次换id就不好用了 而且会导致大量的无用key堆积)

方案二(guava实现)

代码案例
public static final int _1w = 10000;public static final int size = 100 * _1w;public static double fpp = 0.03;/*** 入门demo*/public void bloomFilter() {BloomFilter filter = BloomFilter.create(Funnels.integerFunnel(), 100);System.out.println(filter.mightContain(1));System.out.println(filter.mightContain(2));filter.put(1);filter.put(2);System.out.println(filter.mightContain(1));System.out.println(filter.mightContain(2));}/*** 误判率演示和源码分析*/public void bloomFilter2() {BloomFilter filter = BloomFilter.create(Funnels.integerFunnel(), size);for (int i = 0; i < size; i++) {filter.put(i);}ArrayList list = new ArrayList<>(size);for (int i = 0; i < size; i++) {if (filter.mightContain(i)) {list.add(i);}}System.out.println("存在的数量" + list.size());ArrayList arrayList = new ArrayList<>(10 * _1w);for (int i = size + 1; i < size + 100000; i++) {if (filter.mightContain(i)) {System.out.println(i + "被误判了");arrayList.add(i);}}System.out.println("误判的数量" + arrayList.size());}public static void main(String[] args) {new GuavaBBloomFilterDemo().bloomFilter2();}
 
源码分析

guava布隆过滤器新建

当你的误判率fpp越低,需要占用的bit数组就越长,对值进行hash计算的hash函数就越多,这样的话能更加避免hash冲突的情况发生,用空间和时间来换取准确率,guava默认设置是0.03,个人用的话最低也就建议到0.01,再低的话导致程序变慢就得不偿失了.

方案三(RedisSon实现)

代码实现
public static final int _1w = 10000;public static final int size = 100 * _1w;public static double fpp = 0.01;static RedissonClient redissonClient;static RBloomFilter rBloomFilter;static {Config config = new Config();config.useSingleServer().setAddress("redis://8.131.64.231:16678").setDatabase(0).setPassword("liang#0601");redissonClient = Redisson.create(config);rBloomFilter = redissonClient.getBloomFilter("phoneList", new StringCodec());rBloomFilter.tryInit(size, fpp);rBloomFilter.add("10086");redissonClient.getBucket("10086", new StringCodec()).set("chinamobile10086");}public static String getPhone(String id) {String result;if (rBloomFilter.contains(id)) {RBucket rBucket = redissonClient.getBucket(id, new StringCodec());result = rBucket.get();if (result != null) {return "result form redis:" + result;} else {result = getByMysql(id);if (result == null) {return null;}redissonClient.getBucket(id, new StringCodec()).set(result);}return "result form mysql:" + result;}return null;}public static String getByMysql(String id) {return "10086mysql";}public static void main(String[] args) {String phone = getPhone("10086");System.out.println(phone);redissonClient.shutdown();}

方案四(直接安装redis插件,应用层解决方案)

编译安装Rebloom插件

编译安装
编译安装

docker安装

常用操作命令

默认的误判率是0.01 默认的bit数组是100

缓存击穿

定义

热点key突然失效了,导致大量的请求直接打到了MySQL上面

解决方案

  • 互斥更新(在第一个线程进来拿数据的时候,如果发现redis里面没有就用互斥锁锁住,更新进入redis之后在放开锁)
  • 随机退避
  • 双缓存结构解决
  • 开启两块缓存,主A从B,先更新B再去更新A,严格按照这个顺序
  • 先查询主缓存A,A没有再去查询从缓存B
  • 注意更新和查询的顺序要倒过来,这样就能避免有时间差

两个主从缓存差异化失效时间,在你删除缓存的时候就不会缓存击穿

缓存问题总结图

相关内容

热门资讯

安卓9.0系统挂机游戏,轻松享... 你有没有发现,自从安卓9.0系统更新后,手机里的游戏体验简直就像坐上了火箭!今天,就让我带你一起探索...
安卓系统怎么用迅雷下载,安卓系... 你有没有想过,在安卓系统上下载文件竟然也能这么简单?没错,今天就要来给你揭秘,如何用迅雷在安卓系统上...
安卓手机刷成学生系统,探索全新... 你有没有想过,你的安卓手机其实可以变身成一个充满学习氛围的学生系统呢?没错,就是那种看起来简洁、功能...
ios能迁移安卓系统吗,iOS... 你有没有想过,你的iPhone里的那些宝贝应用,能不能搬到安卓手机上继续使用呢?这可是不少手机用户的...
荣耀10安卓11系统,畅享极致... 你知道吗?最近手机界可是热闹非凡呢!荣耀10这款手机,自从升级到了安卓11系统,简直就像脱胎换骨了一...
安卓系统pc版电脑配置,打造流... 你有没有想过,安卓系统竟然也能在电脑上运行呢?没错,就是那个我们手机上常用的安卓系统,现在也能在PC...
tcllinux系统刷安卓系统... 你有没有想过,你的TCL Linux系统竟然也能升级成安卓系统呢?没错,就是那个我们日常使用的安卓系...
安卓13系统更新蓝牙,蓝牙功能... 你有没有发现,最近你的安卓手机好像变得不一样了?没错,就是那个神秘的安卓13系统更新,它悄悄地来到了...
安卓系统钉钉打开声音,安卓系统... 你有没有遇到过这种情况?手机里装了钉钉,可每次打开它,那声音就“嗖”地一下跳出来,吓你一跳。别急,今...
理想汽车操作系统安卓,基于安卓... 你有没有想过,一辆汽车,除了能带你去你想去的地方,还能像智能手机一样,给你带来智能化的体验呢?没错,...
安卓系统越狱还能升级吗,升级之... 你有没有想过,你的安卓手机越狱后,还能不能愉快地升级系统呢?这可是不少手机爱好者关心的大问题。今天,...
安卓系统蓝牙耳机拼多多,畅享无... 你有没有发现,最近蓝牙耳机在市场上可是火得一塌糊涂呢!尤其是安卓系统的用户,对于蓝牙耳机的要求那可是...
安卓变苹果系统桌面,桌面系统变... 你知道吗?最近有个大新闻在科技圈里炸开了锅,那就是安卓用户纷纷转向苹果系统桌面。这可不是闹着玩的,这...
鸿蒙系统怎么下安卓,鸿蒙系统下... 你有没有想过,你的手机里那个神秘的鸿蒙系统,竟然也能和安卓世界来一场亲密接触呢?没错,今天就要来揭秘...
手机安卓系统流程排行,便捷操作... 你有没有发现,现在手机的世界里,安卓系统就像是个大舞台,各种版本层出不穷,让人眼花缭乱。今天,就让我...
安卓系统左上角hd,左上角HD... 你有没有发现,每次打开安卓手机,左上角那个小小的HD标识总是默默地在那里,仿佛在诉说着什么?今天,就...
安卓系统软件文件,架构解析与功... 你有没有发现,手机里的安卓系统软件文件就像是一个神秘的宝库,里面藏着无数的宝藏?今天,就让我带你一起...
安卓系统输入法回车,探索安卓输... 你有没有发现,在使用安卓手机的时候,输入法回车键的奇妙之处?它就像是我们指尖的魔法师,轻轻一点,文字...
安卓修改系统时间的软件,轻松掌... 你有没有想过,有时候手机上的时间不对劲,是不是觉得生活节奏都被打乱了?别急,今天就来给你揭秘那些神奇...
安卓系统能改成鸿蒙吗,系统迁移... 你有没有想过,你的安卓手机能不能变成一个鸿蒙系统的“小清新”呢?这可不是天方夜谭哦,今天就来聊聊这个...