千万级数据去重其实并不复杂

之前曾经看过一句话觉得挺好,大概的意思就是不同的数据结构有不同的适用场景和优缺点,需要仔细权衡自己的需求之后妥善适用它们。感觉布隆过滤器的实现是正好印证了这句话。

一、原理

布隆过滤器本质上是一种比较巧妙的概率型数据结构,用来告诉我们某个东西一定不存在或可能存在,特点是高效的插入和查询,但不支持删除。

布隆过滤器不保存数据本身,而是通过 K 个hash 函数来计算在 byte[] 数组中的存放位置,并把这些个位置置为 1。如果计算结果所有需要置起的位置对应的值都是0,则认为该值不存在,如果存在值为1的位置(表示该位置被其他数据设置过),则认为该值可能存在。所以相比List、Map这种数据结构,它更省内存,可以被用来处理数据过滤、黑名单、处理缓存穿透等问题。举个例子:
在这里插入图片描述
假设我们布隆过滤器长度为10,同时有3个hash函数,我们给定一个数据为”hello“,通过3个hash函数计算后得到位置分别为1,4,7,假设此时这三个位置上的值都为0,表明该数据不存在。给定另一个数据为”sun“,计算后得到位置为2,7,9,此时位置7已经被置为1,则认为该数据可能存在。可见,布隆过滤器的容错跟本身定义的容量和整体的数据量的大小有关,容量一定的情况下,数据量越大,出现误判的可能性越大。
在这里插入图片描述
对于布隆过滤器,Guava、Redis本身已经有实现,就不用重复去造轮子了。

二、基于Guava实现

2.1 添加依赖:
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>19.0</version>
</dependency>
2.2 增加两个配置项信息
bloomFilter.elementSize=10000000 //布隆过滤器预估存放的最大值
bloomFilter.errorProbability=0.0000001 //误判率
2.3 对布隆过滤器做一个封装,方便操作数据:
public interface BloomFilterWrap {

    boolean add(String info);

    boolean clear();
}
2.4 接口实现:
@Component
public class RepeatFilterWrap implements BloomFilterWrap{

    @Value("${bloomFilter.elementSize}")
    private long elementSize;
    
    @Value("${bloomFilter.errorProbability}")
    private double errorProbability;
    
    private BloomFilter<String> bloomFilter;

    @PostConstruct
    private void init() throws Exception{
        initBloomFilter();
    }

    @Override
    public boolean add(String info) {
        if(bloomFilter.mightContain(info)){
            return false;
        }
        bloomFilter.put(info);
        return true;
    }

    @Override
    public boolean clear() {
        initBloomFilter();
        return true;
    }

    private void initBloomFilter(){
        bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), elementSize, errorProbability);
    }
}

三、效果

一千万条数据,误判率百万分之一,最后计算出来占用的内存只有40M。在公司实际项目中,存在着大量的黑名单在数据发送的时候需要被过滤,就采用了布隆过滤器和Redis配合校验,每次发送的时候会先判断数据是否存在布隆过滤器中,存在的话再去查Redis中是否存在,避免每次请求都去查Redis,效果还是很可观的。
在这里插入图片描述

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芋圆在睡觉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值