文章目录

  • 问题描述
  • 解决方案
    • BloomFilter(布隆过滤器)
      • fpp
      • 布隆过滤器的特点
      • 布隆过滤器中的数据可不可以删除
      • 布隆过滤器应该设计为多大?
      • 布隆过滤器应该使用多少个哈希函数?
      • 布隆过滤器的时间复杂度和空间复杂度?
      • Guava的布隆过滤器的实现
    • BitMap

问题描述

在开发过程中,经常要判断一个元素是否在一个集合中。假设你现在要给项目添加IP黑名单功能,此时你手上有大约 1亿个恶意IP的数据集,有一个IP发起请求,你如何判断这个IP在不在你的黑名单中?

类似这种问题用Java自己的Collection和Map很难处理,因为它们存储元素本身,会造成内存不足,而我们只关心元素存不存,对于元素的值我们并不关心,具体值是什么并不重要。

解决方案

BloomFilter(布隆过滤器)

布隆过滤器可以用来判断某个元素是否在集合内,具有运行快速,内存占用小的特点,它是一个保存了很长的二级制向量,同时结合 Hash 函数实现的。而高效插入和查询的代价就是,它是一个基于概率的数据结构,只能告诉我们一个元素绝对不在集合内,对于存在集合内有一定的误判率

fpp

因为布隆过滤器中总是会存在误判率,因为哈希碰撞是不可能百分百避免的。布隆过滤器对这种误判率称之为假阳性概率,即:False Positive Probability,简称为 fpp。

在实践中使用布隆过滤器时可以自己定义一个 fpp,然后就可以根据布隆过滤器的理论计算出需要多少个哈希函数和多大的位数组空间。需要注意的是这个 fpp 不能定义为 100%,因为无法百分保证不发生哈希碰撞。

下图表示向布隆过滤器中添加元素 https://blog.csdn.net/booksseahttps://www.abc.com 的过程,它使用了 func1 和 func2 两个简单的哈希函数。

对写入的数据做 H 次 hash 运算定位到数组中的位置,同时将数据改为 1 。当有数据查询时也是同样的方式定位到数组中。 一旦其中的有一位为 0 则认为数据肯定不存在于集合,否则数据可能存在于集合中。

通过其原理可以知道,可我们可以提高数组长度以及 hash 计算次数来降低误报率,但是相应的 CPU、内存的消耗也会相应的提高;这需要我们根据自己的业务需要去权衡选择。

布隆过滤器的特点

布隆过滤有以下2个特点:

  • 只要返回数据不存在,则肯定不存在。
  • 返回数据存在,但只能是大概率存在。

在有限的数组长度中存放大量的数据,即便是再完美的 Hash 算法也会有冲突,所以有可能两个完全不同的 A、B 两个数据最后定位到的位置是一模一样的。这时拿 B 进行查询时那自然就是误报了。

布隆过滤器中的数据可不可以删除

布隆过滤器判断一个元素存在就是判断对应位置是否为 1 来确定的,但是如果要删除掉一个元素是不能直接把 1 改成 0 的,因为这个位置可能存在其他元素,所以如果要支持删除,最简单的做法就是加一个计数器,就是说位数组的每个位如果不存在就是 0,存在几个元素就存具体的数字,而不仅仅只是存 1,那么这就有一个问题,本来存 1 就是一位就可以满足了,但是如果要存具体的数字比如说 2,那就需要 2 位了,所以带有计数器的布隆过滤器会占用更大的空间。

<dependency><groupId>com.baqend</groupId><artifactId>bloom-filter</artifactId><version>1.0.7</version>
</dependency>

新建一个带有计数器的布隆过滤器 CountingBloomFilter:

package com.lonelyWolf.redis.bloom;import orestes.bloomfilter.FilterBuilder;public class CountingBloomFilter {public static void main(String[] args) {orestes.bloomfilter.CountingBloomFilter<String> cbf = new FilterBuilder(10000,0.01).countingBits(8).buildCountingBloomFilter();cbf.add("zhangsan");cbf.add("lisi");cbf.add("wangwu");System.out.println("是否存在王五:" + cbf.contains("wangwu")); //truecbf.remove("wangwu");System.out.println("是否存在王五:" + cbf.contains("wangwu")); //false}
}

构建布隆过滤器前面 2 个参数一个就是期望的元素数,一个就是 fpp 值,后面的 countingBits 参数就是计数器占用的大小,这里传了一个 8 位,即最多允许 255 次重复,如果不传的话这里默认是 16 位大小,即允许 65535次重复。

建议使用Guava自带的布隆过滤器,直接传入预期的数据量以及fpp,它会自动帮我们计算数组长度和哈希次数

布隆过滤器应该设计为多大?

假设在布隆过滤器里面有 k 个哈希函数,m 个比特位(也就是位数组长度),以及 n 个已插入元素,错误率会近似于 (1-ekn/m)k,所以你只需要先确定可能插入的数据集的容量大小 n,然后再调整 k 和 m 来为你的应用配置过滤器。

布隆过滤器应该使用多少个哈希函数?

对于给定的 m(比特位个数)和 n(集合元素个数),最优的 k(哈希函数个数)值为: (m/n)ln(2)

布隆过滤器的时间复杂度和空间复杂度?

对于一个 m(比特位个数)和 k(哈希函数个数)值确定的布隆过滤器,添加和判断操作的时间复杂度都是 O(k),这意味着每次你想要插入一个元素或者查询一个元素是否在集合中,只需要使用 k 个哈希函数对该元素求值,然后将对应的比特位标记或者检查对应的比特位即可。

Guava的布隆过滤器的实现

Guava有自带的布隆过滤器的实现

public class BloomFilterTest {public static void main(String[] args) {long star = System.currentTimeMillis();BloomFilter<Integer> filter = BloomFilter.create(Funnels.integerFunnel(),//预计存放多少数据10000000,//可以接受的误报率0.01);for (int i = 0; i < 10000000; i++) {filter.put(i);}Assert.isTrue(filter.mightContain(1),"不存在");Assert.isTrue(filter.mightContain(2),"不存在");Assert.isTrue(filter.mightContain(3),"不存在");Assert.isTrue(filter.mightContain(10000000),"不存在");long end = System.currentTimeMillis();System.out.println("执行时间:" + (end - star));}
}

BitMap

BitMap不会存在误判的情况,位图也是布隆过滤器的实现,但是占用内存空间随集合内最大元素的增大而增大。而布隆过滤器,因为其可能一个bit为多个元素作标识,这就保证了它的空间利用率。这2种方式根据业务进行选择。

以32位整型为例,它可以表示数字的个数为2^32. 可以申请一个位图,让每个整数对应的位图中的一个bit,这样2^32个数需要的位图的大小为512MB。具体实现的思路为:申请一个512MB的位图,并把所有的位都初始化为0;接着遍历所有的整数,对遍历到的数字,把相应的位置上的bit设置为1.最后判断待查找的数对应的位图上的值是多少,如果是0,那么表示这个数字不存在,如果是1,那么表示这个数字存在。

Java中有BitMap的实现类,BitSet

public class BitMapTest {public static void main(String[] args) {int[] array = {3, 8, 5, 7, 1};BitSet bitSet = new BitSet(5);for (int i = 0; i < array.length; i++) {bitSet.set(array, true);}bitSet.stream().forEach(e -> System.out.println(e));}
}

Redis里也有BitMap的实现。这个下回出篇文章讲。

【大数据】亿级数据中判断一个数是否存在相关推荐

  1. 【算法】BloomFilter 如何判断一个元素在亿级数据中是否存在?

    1.概述 转载: 如何判断一个元素在亿级数据中是否存在? 前言 最近有朋友问我这么一个面试题目: 现在有一个非常庞大的数据,假设全是 int 类型.现在我给你一个数,你需要告诉我它是否存在其中(尽量高 ...

  2. 大数据在智慧城市中的应用

    摘要:文章首先介绍了大数据和智慧城市的概念.大数据的应用潜力和当前国际上智慧城市的建设概况,然后简要介绍了大数据的四个方面共16种关键技术,最后参考欧盟提出的大数据在智慧城市应用的九个方面,提出了自己 ...

  3. 学术前沿丨大数据在劳动力市场研究中的应用与展望

    推荐语:专业的网络招聘平台.微博微信等网络社交平台以及谷歌百度等互联网搜索引擎在降低信息不对称的基础上,极大地减少了信息搜索成本,促进了劳动力供给与需求的高效匹配,形成了具有动态性.及时性的海量劳动力 ...

  4. 2018.11:大数据在政府统计中的应用、瓶颈及融合路径(余芳东)

    内容摘要:应用大数据是未来政府统计发展的必然趋势.本文系统梳理当前政府统计应用大数据的基本类型,研究探索大数据统计应用实践和基本方法思路,剖析大数据统计应用面临的困难和瓶颈,提出推进大数据与政府统计工 ...

  5. 【2017年第3期】电信大数据在信用风险管理中的应用

    刘新海1,韩涵2,丁伟3,王题3 1. 中国人民银行征信中心,北京 100031 2. 中国信息通信研究院,北京 100191 3. 中国联合网络通信有限公司网络技术研究院,北京 100048 摘要: ...

  6. 解读大数据技术在金融行业中的应用

    最近在了解大数据在各行各业中的应用开发,以及产生的商业价值,文章对金融行业的分析,贴出来欢迎大家指正. 大数据技术在金融行业中应用主要以银行.证券.保险等金融细分领域为主. 银行 银行大数据应用可以分 ...

  7. 大数据技术在建筑节能中的应用探究

    本文内容来自下面的文章: 陈庆财,鹿伟,王福林,窦强.大数据技术在建筑节能中的应用案例研究[J].建筑节能,2019,47(10):105-108+116. 大数据技术在建筑节能中的应用案例研究 基金 ...

  8. 大数据技术在金融行业中的应用

    1. 概述 近年来,随着大数据.云计算.区块链.人工智能等新技术的快速发展,这些新技术与金融业务深度融合,释放出了金融创新活力和应用潜能,这大大推动了我国金融业转型升级,助力金融更好地服务实体经济,有 ...

  9. hadloop大数据平台论文_企业大数据平台建设过程中的问题和建议

    2 0 1 7 年 第 1 2 期 信 息 通 信 2017 (总第 180 期) INFORMATION & COMMUNICATIONS ( Sum . N o 180) 企业大数据平台建 ...

最新文章

  1. bamboo php,建立数据模型 — asbamboo php framework 文档
  2. linux shell编程语句if、case.
  3. 如何降低微服务测试成本?我的经验之谈
  4. 分布式系统中的领导选举
  5. ★LeetCode(182)——查找重复的电子邮箱(MySQL)
  6. jQuery 查找元素节点
  7. 数据库系统概论第五版(第 5 章 数据库完整性)笔记
  8. python爬图mzitu_换个框架爬妹子图mzitu解决直接访问的403
  9. 数据的预处理——平滑处理
  10. 支持断点续传的大文件传输协议
  11. SPSS——描述性统计分析——描述
  12. 正确使用 CDN 让你更好规避安全风险
  13. 《猎头局中局》——摘要
  14. 手机设备唯一标识相关概念
  15. 鞋子微商怎么做qq引流?微商如何通过QQ空间引流
  16. 局域网内Linux下开启ftp服务的“曲折路”和命令复习
  17. Metamask不能访问以太坊账户?隐私模式!
  18. 画家王俊杰主编中国艺苑大型名家活动发布会
  19. 【原创】Python 极验滑块验证
  20. 运动手环SRRC认证办理

热门文章

  1. 拉卡拉支付融入创新属性推动行业发展
  2. excel某一列明明是数值,却无法求和?
  3. MySql UNIX_TIMESTAMP和FROM_UNIXTIME函数讲解
  4. 高耐磨、微变形冷作模具用钢及高韧性冷作模具用钢
  5. 共享经济与 O2O 地推结合,阿里先做了
  6. C#的ASP.NET中关于OleDb连接数据库执行增删改查
  7. 解决启动报错Consider defining a bean of type ‘xxx‘ in your configuration.
  8. Reids系列: Redis哨兵模式(Sentinel) (五)
  9. Python开发工具PyCharm使用教程:如何调试python应用程序
  10. 文艺青年转行程序员,一路狂奔