要么游泳,要么沉底,这是我看的一个医生的书里面的一句话,听起来觉得挺极端的,压力很大的,我总结出一个道理,所有励志的话都是让你相信为来是有光的,努力后前途是美丽的,也就是说,践行这句话时,自己要么在游泳,要么在黑暗之中,也许这就是人生需要的起伏,不管是为了激励人而故意弄一个先抑后扬,还是生活中,就是要有波澜起伏。
每日BB结束
今天说说布隆过滤器
布隆过滤器 用来测试一个元素是否在一个集合里。它实际上是一个很长的二进制向量和 一系列随机映射函数
看一个谷歌的实现
/**
* 总个数
*/
private static int total = 1000000;
private static org.slf4j.Logger logger = LoggerFactory.getLogger(Bloom.class);
/**
* 创建布隆过滤器
*/
private static BloomFilter<Integer> bf = BloomFilter.create(Funnels.integerFunnel(), total);
public static void main(String[] args) {
// 初始化1000000条数据到过滤器中
for (int i = 0; i < total; i++) {
bf.put(i);
}
int j = 5000;
// 判断是否存在
boolean flag = bf.mightContain(j);
logger.info("{} 判断结果为:{}", j, flag);
// 匹配已在过滤器中的值,是否有匹配不上的
for (int i = 0; i < total; i++) {
if (!bf.mightContain(i)) {
logger.info("有坏人逃脱了~~~");
}
}
// 匹配不在过滤器中的10000个值,有多少匹配出来
int count = 0;
for (int i = total; i < total + 10000; i++) {
if (bf.mightContain(i)) {
count++;
}
}
logger.info("误伤的数量:" + count);
}
代码也是挺简单的,来说说干货
* 查询优化,有一种可以通过缓存在处理
* 其实还可把查询的结果放到map里面
* 布隆过滤器可以解决这一点,他是一个类似数组类型的数据结构
* 把放到里面的值,通过k次hash放到数组的k个点上,并且将k个点都标记为1
* 查找的时候,也是将要查找的值通过k个hash函数,来从数组中找对应的位置,如果k个位置中
有一个为0,那么就一定不存在
* 如果 都是1 那么也有可能不存在(因为 对于一个布隆过滤器中不存在的值,他去做hash计算,获得到bit数组中的位置,可能被其他的值的hash占用了,被写成了1)
* 缺点就是,存在不准确,以及他是不支持删除的(因为删除,要把元素对应数组中的位置置为0
,但是这个位置是共用的,所以不能删除
* ),但是有一些变种是支持的
* 另外使用多少个key是可以指定的,可以通过计算公式计算出来,这个api不用因为里面已经帮
忙计算过了
* 另外 下面的栗子是使用google gava库里面的 他是单体的不支持分布式
* 所以 用redis的更好一些
* redis实现布隆过滤器有几种形式
* lua 脚本
* reBloom 这个要部署服务
* 还有通过pyton
* 其实具体的实现思想都是一致的
上面说了很多,重要的就是他的数据结构,时间复杂度,布隆一个打辅助的是怎么想到的,另外也有一个疑问就是HashMap因为占内存而不被使用,布隆怎么就不占内存呢,他也是存了很多个数据进去的呀。
HashMap存储容量占比高,考虑到负载因子的存在,通常空间是不能被用满的,而一旦你的值很多例如上亿的时候,那 HashMap 占据的内存大小就会变得非常大,意思就是说,Hash要留一些空间,不能所有都存,但是布隆可以都存的。
而且HashMap在元素数量很多时是不能一次性写入的