Redisson_布隆过滤器
应用场景
去重
诞生背景
Java应用一般通过JDK自身提供的HashSet去重,通过contains()方法判断当前元素是否存在于Set中。该方式要求在调用contains()前,已经将数据列表加载到内存中(即该方法基于内存存储实现判断功能)。
缺点:
1.满足不了分布式环境下的判重
2.高并发产生大数据量的情况下,此种方式容易OOM
简介
布隆过滤器的初始化
需要设计并构造K个哈希函数及容量大小为N、每个元素初始取值为0的位数组
往其中添加元素
当使用布隆过滤器添加 key 时,会使用不同的 hash 函数对 key 存储的元素值进行哈希计算,从而会得到多个哈希值。根据哈希值计算出一个整数索引值,将该索引值与位数组长度做取余运算,最终得到一个位数组位置,并将该位置的值变为 1
判断元素是否存在及误判原因
将当前的元素经过K个哈希函数计算得到K个哈希值,然后判断K个哈希值(数组的下标)对应数组中的取值是否均为1(若为1则一定存在);反之,则不一定存在。What???
误判原因:比如,元素1 和 元素2,这两个元素同时将一个位置变为了 1(如下图所示)。在这种情况下,我们就不能判定“元素 1”一定存在,这是布隆过滤器存在误判的根本原因。
优缺点分析
优点在于它不需要开辟额外的内存存储元素,从而节省了存储空间;缺点在于判断元素是否在集合中时,有一定的误判率,并且添加进布隆过滤器的元素是无法删除的,因为位数组的下标是多个元素“共享”的,如果删除的话,很有可能出现“误删”的情况。
代(上)码(菜)
基本数据类型
public void testBaseBloom() {//定义Redis中的Keyfinal String key = "myBloomFilterBaseData";//初始化构造数组容量的大小Long total = 100L;//创建布隆过滤器组件RBloomFilter<Integer> bloomFilter = redissonClient.getBloomFilter(key);//初始化布隆过滤器,预计统计元素数量为100,期望误差率为0.01bloomFilter.tryInit(total, 0.01);//初始化遍历往布隆过滤器添加元素for (int i = 1; i <= total; i++) {bloomFilter.add(i);}//检查特定的元素在布隆过滤器中是否存在并打印输出log.info("该布隆过滤器是否包含数据1:{}", bloomFilter.contains(1));log.info("该布隆过滤器是否包含数据-1:{}", bloomFilter.contains(-1));log.info("该布隆过滤器是否包含数据100:{}", bloomFilter.contains(10000));log.info("该布隆过滤器是否包含数据100000:{}", bloomFilter.contains(100000));}
包装数据类型
public void testDtoBloom(){//定义Redis中的Keyfinal String key="myBloomFilterDtoData";//创建布隆过滤器组件RBloomFilter<BloomDto> bloomFilter=redissonClient.getBloomFilter(key);//初始化布隆过滤器,预计统计元素数量为1000,期望误差率为0.01bloomFilter.tryInit(1000, 0.01);//初始化遍历向布隆过滤器中添加对象BloomDto dto1=new BloomDto(1, "1");BloomDto dto2=new BloomDto(10, "10");BloomDto dto3=new BloomDto(100, "100");BloomDto dto4=new BloomDto(1000, "1000");BloomDto dto5=new BloomDto(10000, "10000");//向布隆过滤器中添加对象bloomFilter.add(dto1);bloomFilter.add(dto2);bloomFilter.add(dto3);bloomFilter.add(dto4);bloomFilter.add(dto5);//检查特定的元素在布隆过滤器中是否存在并打印输出log.info("该布隆过滤器是否包含数据(1, \\"1\\"):{}", bloomFilter.contains(newBloomDto(1, "1")));log.info("该布隆过滤器是否包含数据(100, \\"2\\"):{}", bloomFilter.contains(new BloomDto(100, "2")));log.info("该布隆过滤器是否包含数据(1000, \\"3\\"):{}", bloomFilter.contains(new BloomDto(1000, "3")));log.info("该布隆过滤器是否包含数据(10000, \\"10000\\"):{}", bloomFilter.contains(new BloomDto(10000, "10000")));}