【Redis】Redis中的布隆过滤器

这篇具有很好参考价值的文章主要介绍了【Redis】Redis中的布隆过滤器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【Redis】Redis中的布隆过滤器

前言

在实际开发中,会遇到很多要判断一个元素是否在某个集合中的业务场景,类似于垃圾邮件的识别,恶意IP地址的访问,缓存穿透等情况。类似于缓存穿透这种情况,有许多的解决方法,如:Redis存储Null值等,而对于垃圾邮件的识别,恶意IP地址的访问,我们也可以直接用 HashMap 去存储恶意IP地址以及垃圾邮件,然后每次访问时去检索一下对应集合中是否有相同数据。这种思路对于数据量小的项目来说是没有问题的,但是对于大数据量的项目,如:垃圾邮件出现有几十万,恶意IP地址出现有上百万,那么这些大量的数据就会占据大量的空间,这个时候就可以考虑一下布隆过滤器了。

布隆过滤器是什么?

布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。

【Redis】Redis中的布隆过滤器,后端,Redis,redis,缓存

可以把布隆过滤器理解为一个不怎么精确的 set 结构,当你使用它的 contains方法判断某个对象是否存在时,它可能会误判。但是布隆过滤器也不是特别不精确,只要参数设置得合理,它的精确度也可以控制得相对足够精确,只会有小小的误判概率。

当布隆过滤器说某个值存在时,这个值可能不存在;当它说某个值不存在时那就肯定不存在。打个比方,当它说不认识你时,肯定就是真的不认识;而当它说认识你时,却有可能根本没见过你,只是因为你的脸跟它认识的某人的脸比较相似(某些熟脸的系数组合),所以误判以前认识你。

一句话总结:由一个初始值为零的bit数组和多个哈希函数构成,用来快速判断集合中是否存在某个元素。

使用bit数组的目的就是减少内存的占用,数组不保存数据信息,只是在内存中存储一个是否存在的表示0或1

布隆过滤器的优缺点:

优点:

​ 高效插入和查询,内存占用空间少

缺点:

  • 存在误判,不能精确过滤
  • 不能删除元素

布隆过滤器的使用场景

黑白名单校验、识别垃圾邮件

发现存在黑名单中的,就执行特定操作。比如:识别垃圾邮件,只要是邮箱在黑名单中的邮件,就识别为垃圾邮件。假设黑名单的数量是数以亿计的,存放起来就是非常耗费存储空间的,布隆过滤器则是一个较好的解决方案。把所有黑名单都放在布隆过滤器中,在收到邮件时,判断邮件地址是否在布隆过滤器中即可。

解决缓存穿透的问题

把已存在数据的key存在布隆过滤器中,相当于Redis前面挡着一个布隆过滤器。当有新的请求时,先到布隆过滤器中查询是否存在:如果布隆过滤器中不存在该条数据则直接返回;如果布隆过滤器中已存在,才去查询缓存Redis,如果Redis里没查询到则再查询MySQL数据库

布隆过滤器的原理

每个布隆过滤器对应到 Redis 的数据结构里面就是一个大型的位数组和几个不-样的无偏 hash函数,如下图中的F、G、H就是这样的hash函数。所谓无偏就是能够把元素的 hash 值算得比较均匀,让元素被 hash映射到位数组中的位置比较随机。

【Redis】Redis中的布隆过滤器,后端,Redis,redis,缓存

向布隆过滤器中添加 key 时,会使用多个 hash 函数对 key 进行 hash,算得一个整数索引值,然后对位数组长度进行取模运算得到一个位置,每个 hash 函数都会算得一个不同的位置。再把位数组的这几个位置都置为 1,就完成了 add 操作。

向布隆过滤器询问 key 是否存在时,跟add 一样,也会把 hash 的几个位置都算出来,**看看位数组中这几个位置是否都为 1,只要有一个位为 0,那么说明布隆过滤器中这个 key 不存在。如果这几个位置都是 1,并不能说明这个 key 就一定存在,只是极有可能存在,因为这些位被置为 1 可能是因为其他的 key 存在所致。**如果这个位数组比较稀疏,判断正确的概率就会很大,如果这个位数组比较拥挤,判断正确的概率就会降低。具体的概率计算公式比较复杂,感兴趣可以阅读相关的更深入研究的资料,不过非常烧脑,不建议读者细看。

参考博客:Redis系列–布隆过滤器(Bloom Filter)_redistemplate 布隆过滤器_幼儿园里的山大王的博客-CSDN博客

基于Redisson的布隆过滤器使用实例

1.引入Redisson依赖

<!--原生-->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.13.4</version>
</dependency>

<!--或者另一种Spring集成starter-->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.13.6</version>
</dependency>

2.配置Redisson

@Configuration
public class RedissionConfig {
    @Value("${spring.redis.host}")
    private String redisHost;

    @Value("${spring.redis.password}")
    private String password;

    private int port = 6379;

    @Bean
    public RedissonClient getRedisson() {
        Config config = new Config();
        config.useSingleServer().
                setAddress("redis://" + redisHost + ":" + port).
                setPassword(password);
        config.setCodec(new JsonJacksonCodec());
        return Redisson.create(config);
    }
}

3.配置布隆过滤器

@Configuration
public class BloomFilterConfig {
    
    @Autowired
    private RedissonClient redissonClient;
    
    /**
     * 创建订单号布隆过滤器
     * @return
     */
    @Bean
    public RBloomFilter<Long> orderBloomFilter() {
        //过滤器名称
        String filterName = "orderBloomFilter";
        // 预期插入数量
        long expectedInsertions = 10000L;
        // 错误比率
        double falseProbability = 0.01;
        
        RBloomFilter<Long> bloomFilter = redissonClient.getBloomFilter(filterName);
        bloomFilter.tryInit(expectedInsertions, falseProbability);
        
        return bloomFilter;
    }
}
4.创建订单表
CREATE TABLE `tb_order` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '订单Id',
  `order_desc` varchar(50) NOT NULL COMMENT '订单描述',
  `user_id` bigint NOT NULL COMMENT '用户Id',
  `product_id` bigint NOT NULL COMMENT '商品Id',
  `product_num` int NOT NULL COMMENT '商品数量',
  `total_account` decimal(10,2) NOT NULL COMMENT '订单金额',
  `create_time` datetime NOT NULL COMMENT '创建时间',PRIMARY KEY (`id`),
  KEY `ik_user_id` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

5.编写业务处理代码

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {

    @Resource
    private RBloomFilter<Long> orderBloomFilter;

    @Resource
    private TbOrderMapper  tbOrderMapper;

    @Resource
    private RedisTemplate<String,Object> redisTemplate;


    @Override
    public void createOrder(TbOrder tbOrder) {
        //1、创建订单
        tbOrderMapper.insert(tbOrder);

        //2、订单id保存到布隆过滤器
        log.info("布隆过滤器中添加订单号:{}",tbOrder.getId());
        orderBloomFilter.add(tbOrder.getId());
    }

    @Override
    public TbOrder get(Long orderId) {
        TbOrder tbOrder = null;
        //1、根据布隆过滤器判断订单号是否存在
        if(orderBloomFilter.contains(orderId)){
            log.info("布隆过滤器判断订单号{}存在",orderId);
            String key = "order:"+orderId;
            //2、先查询缓存
            Object object = redisTemplate.opsForValue().get(key);
            if(object != null){
                log.info("命中缓存");
                tbOrder =  (TbOrder)object;
            }else{
                //3、缓存不存在则查询数据库
                log.info("未命中缓存,查询数据库");
                tbOrder = tbOrderMapper.selectById(orderId);
                redisTemplate.opsForValue().set(key,tbOrder);
            }
        }else{
            log.info("判定订单号{}不存在,不进行查询",orderId);
        }
        return tbOrder;
    }
}

6.单元测试

@Test
public void testCreateOrder() {
	for (int i = 0; i < 50; i++) {
		TbOrder tbOrder = new TbOrder();
        tbOrder.setOrderDesc("测试订单"+(i+1));
		tbOrder.setUserId(1958L);
		tbOrder.setProductId(102589L);
		tbOrder.setProductNum(5);
		tbOrder.setTotalAccount(new BigDecimal("300"));
		tbOrder.setCreateTime(new Date());
		orderService.createOrder(tbOrder);
        }
    }
@Test
public void testGetOrder() {
	TbOrder  tbOrder = orderService.get(25L);
	log.info("查询结果:{}", tbOrder.toString());
}

总结

布隆过滤器的原理其实非常简单,就是bitmap + 多重hash,主要优势就是利用非常小的空间就可以实现在大规模数据下快速判断某一对象是否存在,缺点是存在误判的可能,但不会漏判,也就是存在的对象一定会判断为存在,而不存在的对象会有较低的概率为误判为存在,且不支持对象的删除,因为会增加误判的概率。最典型的使用是解决缓存穿透的问题。文章来源地址https://www.toymoban.com/news/detail-661410.html

到了这里,关于【Redis】Redis中的布隆过滤器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Redis 布隆过滤器的原理和实践

    布隆过滤器是一种空间效率高、误判率可控的数据结构,通常用于检索一个元素是否在一个集合中。它是由一个比特向量和多个哈希函数组成的。布隆过滤器可以用于快速检测一个元素是否存在于一个集合中,其主要优点是省内存缺点是有一定的误识别率和删除困难。 Redis

    2024年02月09日
    浏览(31)
  • Redis系列--布隆过滤器(Bloom Filter)

    在实际开发中,会遇到很多要判断一个元素是否在某个集合中的业务场景,类似于垃圾邮件的识别,恶意ip地址的访问,缓存穿透等情况。类似于缓存穿透这种情况,有许多的解决方法,如:redis存储null值等,而对于垃圾邮件的识别,恶意ip地址的访问,我们也可以直接用 H

    2024年02月09日
    浏览(32)
  • Redis系列16:聊聊布隆过滤器(原理篇)

    Redis系列1:深刻理解高性能Redis的本质 Redis系列2:数据持久化提高可用性 Redis系列3:高可用之主从架构 Redis系列4:高可用之Sentinel(哨兵模式) Redis系列5:深入分析Cluster 集群模式 追求性能极致:Redis6.0的多线程模型 追求性能极致:客户端缓存带来的革命 Redis系列8:Bitmap实现

    2024年02月08日
    浏览(31)
  • Redis之布隆过滤器(Bloom Filter)解读

    目录 引进前言 隆过滤器定义 隆过滤器原理  布隆过滤器优缺点 布隆过滤器的使用场景 布谷鸟过滤器(了解)  引进前言 在实际开发中,会遇到很多要 判断一个元素是否在某个集合中 的业务场景,类似于垃圾邮件的识别,恶意ip地址的访问,缓存穿透等情况。类似于缓存穿透

    2024年02月09日
    浏览(26)
  • Springboot 在 redis 中使用 BloomFilter 布隆过滤器机制

    在 pom.xml 文件中,引入Spring Boot和Redis相关依赖 创建一个布隆过滤器配置类 BloomFilterConfig : 创建一个BloomFilterController。使用布隆过滤器判断数据是否存在,从而避免缓存穿透: 向里面添加元素  获取元素

    2024年02月13日
    浏览(28)
  • Springboot 在 redis 中使用 Guava 布隆过滤器机制

    在 pom.xml 文件中,引入Spring Boot和Redis相关依赖 创建一个布隆过滤器配置类 BloomFilterConfig : 创建一个BloomFilterController。使用布隆过滤器判断数据是否存在,从而避免缓存穿透: 向里面添加元素  获取元素

    2024年02月12日
    浏览(27)
  • python+redis实现布隆过滤器(含redis5.0版本以上和5.0以下版本的两份代码)

    布隆过滤器是一种空间效率极高的概率数据结构,用于测试一个元素是否是集合的成员。如果布隆过滤器返回 False ,则元素绝对不在集合中。如果返回 True ,则元素可能在集合中,但也可能是一个误报。布隆过滤器利用了多个不同的哈希函数对元素进行哈希,并将结果的位置

    2024年02月10日
    浏览(35)
  • 深入理解PHP+Redis实现布隆过滤器(亿级大数据处理和黑客攻防必备)

    英文名称Bloom Filter,用于判断一个元素是否在一个大数据集合中,如果检测到存在则有可能存在,如果不存在则一定不存在。 Redis官网对于布隆过滤器的说明:https://redis.io/docs/data-types/probabilistic/bloom-filter/ 防止缓存穿透:用于快速判断某个商品数据是否存在于缓存中,如果存

    2024年04月09日
    浏览(35)
  • 【SpringBoot篇】基于布隆过滤器,缓存空值,解决缓存穿透问题 (商铺查询时可用)

    缓存穿透是指在使用缓存机制时,大量的请求无法从缓存中获取到结果,导致请求都要直接访问后端存储系统,从而增加了系统的负载和响应时间。 通常的缓存机制是将请求的结果缓存在内存或其他高速存储介质中,当相同的请求再次到达时,可以直接从缓存中获取结果,避

    2024年02月04日
    浏览(32)
  • 布隆过滤器及其在Java中的实际应用

    布隆过滤器一直是面试中的重点,本篇文章将深入探讨Java中的布隆过滤器的底层思想,包括它的工作原理、优缺点等。同时,我们将结合一个小实际案例,来给大家展示布隆过滤器在解决实际问题中的应用。 在数据处理领域,我们经常需要判断一个元素是否在一个集合中。

    2024年02月05日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包