版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013278314/article/details/83027781
简介
Redis中有一个数据结构叫做Bitmap(下方有官网详解),它提供一个最大长度为512MB(2^32)的位数组。我们可以把它提供给布隆过滤器做位数组。
根据《数学之美》中给出的数据,在使用8个哈希函数的情况下,512MB大小的位数组在误报率万分之五的情况下可以对约两亿的url去重。而若单纯的使用set()去重的话,以一个url64个字节记,两亿url约需要128GB的内存空间,不敢想象。
我使用的策略是使用哈希函数算出的哈希值对2^32取模,填入bitmap中。
本文主要是介绍这种思想和用法,具体业务使用过程中,需要具体实现,下面贴出代码 演示最简单的一种使用方法:
/*
* 模拟项目启动时候 从"数据库"或者其他地方获取到的过滤器集合的数据
*/
static List<String> l = new ArrayList<String>();
// 模拟生成的订单号/用户/商品ID
static {
l.add("201810120001");
l.add("201810120002");
l.add("201810120003");
l.add("201810120004");
}
/**
* 单机版测试
*/
@Test
public void TestRedis() {
Jedis jedis = new Jedis("192.168.1.118", 6379);
// 获取redis支持的最大长度作为取模的基数
double size = Math.pow(2, 32);
// 循环l 取出里面的数据,放入到redis中
l.forEach(orderId -> {
long index = Math.abs((long) (orderId.hashCode() % size));
jedis.setbit("orderId", index, true);
});
// 判断指定值是否在过滤器里面
String orderId = l.get(0);
//String orderId = "201810120005";
long index = Math.abs((long) (orderId.hashCode() % size));
boolean contain = jedis.getbit("orderId", index);
// 为true 说明在里面
if (contain) {
System.out.println("包含这个值.");
// 否则不在
} else {
System.out.println("不包含这个值.");
}
jedis.close();
}
运行结果 orderId如果在l集合里面 就显示包含,否则就不包含