布隆过滤器( Bloom filters)

数据块索引提供了一个有效的方法,在访问一个特定的行时用来查找应该读取的HFile的数据块。但是它的效用是有限的。HFile数据块的默认大小是64KB,这个大小不能调整太多。

如果你要查找一个短行,只在整个数据块的起始行键上建立索引无法给你细粒度的索引信息。例如,如果你的行占用100字节存储空间,一个64KB的数据块包含(64 * 1024)/100 = 655.53 = ~700行,而你只能把起始行放在索引位上。你要查找的行可能落在特定数据块上的行区间里,但也不是肯定存放在那个数据块上。这有多种情况的可能,或者该行在表里不存在,或者存放在另一个HFile里,甚至在MemStore里。这些情况下,从硬盘读取数据块会带来IO开销,也会滥用数据块缓存。这会影响性能,尤其是当你面对一个巨大的数据集并且有很多并发读用户时。

布隆过滤器允许你对存储在每个数据块的数据做一个反向测试。当某行被请求时,先检查布隆过滤器看看该行是否不在这个数据块。布隆过滤器要么确定回答该行不在,要么回答它不知道。这就是为什么我们称它是反向测试。布隆过滤器也可以应用到行里的单元上。当访问某列标识符时先使用同样的反向测试。

布隆过滤器也不是没有代价。存储这个额外的索引层次占用额外的空间。布隆过滤器随着它们的索引对象数据增长而增长,所以行级布隆过滤器比列标识符级布隆过滤器占用空间要少。当空间不是问题时,它们可以帮助你榨干系统的性能潜力。

你可以在列族上打开布隆过滤器,如下所示:

hbase(main)> create 'mytable',{NAME=>'colfam1',BLOOMFILTER=>'ROWCOL'}

BLOOMFILTER参数的默认值是NONE。一个行级布隆过滤器用ROW打开,列标识符级布隆过滤器用ROWCOL打开。行级布隆过滤器在数据块里检查特定行键是否不存在,列标识符级布隆过滤器检查行和列标识符联合体是否不存在。ROWCOL布隆过滤器的开销高于ROW布隆过滤器。

1、主要功能
提高随机读的性能
 
2、存储开销
bloom filter的数据存在StoreFile的meta中,一旦写入无法更新,因为StoreFile是不可变的。Bloomfilter是一个列族(cf)级别的配置属性,如果你在表中设置了Bloomfilter,那么HBase会在生成StoreFile时包含一份bloomfilter结构的数据,称其为MetaBlock;MetaBlock与DataBlock(真实的KeyValue数据)一起由LRUBlockCache维护。所以,开启bloomfilter会有一定的存储及内存cache开销。 
 
3、控制粒度
a)ROW
根据KeyValue中的row来过滤storefile 
举例:假设有2个storefile文件sf1和sf2, 
sf1包含kv1(r1 cf:q1 v)、kv2(r2 cf:q1 v) 
sf2包含kv3(r3 cf:q1 v)、kv4(r4 cf:q1 v) 
如果设置了CF属性中的bloomfilter为ROW,那么get(r1)时就会过滤sf2,get(r3)就会过滤sf1 
b)ROWCOL
根据KeyValue中的row+qualifier来过滤storefile
举例:假设有2个storefile文件sf1和sf2, 
sf1包含kv1(r1 cf:q1 v)、kv2(r2 cf:q1 v) 
sf2包含kv3(r1 cf:q2 v)、kv4(r2 cf:q2 v) 
如果设置了CF属性中的bloomfilter为ROW,无论get(r1,q1)还是get(r1,q2),都会读取sf1+sf2;而如果设置了CF属性中的bloomfilter为ROWCOL,那么get(r1,q1)就会过滤sf2,get(r1,q2)就会过滤sf1
 
 
4、常用场景
1、根据key随机读时,在StoreFile级别进行过滤
2、读数据时,会查询到大量不存在的key,也可用于高效判断key是否存在
 
 
 
5、举例说明
假设x、y、z三个key存在于table中,W不存在
使用Bloom Filter可以帮助我们减少为了判断key是否存在而去做Scan操作的次数
step1)分别对x、y、z运算hash函数取得bit mask,写到Bloom Filter结构中
step2)对W运算hash函数,从Bloom Filter查找bit mask
   如果不存在:三个Bit位至少有一个为0,W肯定不存在该(Bloom Filter不会漏判)
   如果存在   :三个Bit位全部全部等于1,路由到负责W的Region执行scan,确认是否真的存在(Bloom Filter有极小的概率误判)
 
 
 
6、源码解析
1.get操作会enable bloomfilter帮助剔除掉不会用到的Storefile
在scan初始化时(get会包装为scan)对于每个storefile会做shouldSeek的检查,如果返回false,则表明该storefile里没有要找的内容,直接跳过
  1. if (memOnly == false
  2. && ((StoreFileScanner) kvs).shouldSeek(scan, columns)) {
  3. scanners.add(kvs);
  4. }
shouldSeek方法:如果是scan直接返回true表明不能跳过,然后根据bloomfilter类型检查。
  1. if (!scan.isGetScan()) {
  2. return true;
  3. }
  4. byte[] row = scan.getStartRow();
  5. switch (this.bloomFilterType) {
  6. case ROW:
  7. return passesBloomFilter(row, 0, row.length, null, 0, 0);
  8. case ROWCOL:
  9. if (columns != null && columns.size() == 1) {
  10. byte[] column = columns.first();
  11. return passesBloomFilter(row, 0, row.length, column, 0, column.length);
  12. }
  13. // For multi-column queries the Bloom filter is checked from the
  14. // seekExact operation.
  15. return true;
  16. default:
  17. return true;
  18. }
2.指明qualified的scan在配了rowcol的情况下会剔除不会用掉的StoreFile。
对指明了qualify的scan或者get进行检查:seekExactly
  1. // Seek all scanners to the start of the Row (or if the exact matching row
  2. // key does not exist, then to the start of the next matching Row).
  3. if (matcher.isExactColumnQuery()) {
  4. for (KeyValueScanner scanner : scanners)
  5. scanner.seekExactly(matcher.getStartKey(), false);
  6. } else {
  7. for (KeyValueScanner scanner : scanners)
  8. scanner.seek(matcher.getStartKey());
  9. }
如果bloomfilter没命中,则创建一个很大的假的keyvalue,表明该storefile不需要实际的scan
  1. public boolean seekExactly(KeyValue kv, boolean forward)
  2. throws IOException {
  3. if (reader.getBloomFilterType() != StoreFile.BloomType.ROWCOL ||
  4. kv.getRowLength() == 0 || kv.getQualifierLength() == 0) {
  5. return forward ? reseek(kv) : seek(kv);
  6. }
  7. boolean isInBloom = reader.passesBloomFilter(kv.getBuffer(),
  8. kv.getRowOffset(), kv.getRowLength(), kv.getBuffer(),
  9. kv.getQualifierOffset(), kv.getQualifierLength());
  10. if (isInBloom) {
  11. // This row/column might be in this store file. Do a normal seek.
  12. return forward ? reseek(kv) : seek(kv);
  13. }
  14. // Create a fake key/value, so that this scanner only bubbles up to the top
  15. // of the KeyValueHeap in StoreScanner after we scanned this row/column in
  16. // all other store files. The query matcher will then just skip this fake
  17. // key/value and the store scanner will progress to the next column.
  18. cur = kv.createLastOnRowCol();
  19. return true;
  20. }
这边为什么是rowcol才能剔除storefile纳,很简单,scan是一个范围,如果是row的bloomfilter不命中只能说明该rowkey不在此storefile中,但next rowkey可能在。而rowcol的bloomfilter就不一样了,如果rowcol的bloomfilter没有命中表明该qualifiy不在这个storefile中,因此这次scan就不需要scan此storefile了!
 
 
 
7、总结
1.任何类型的get(基于rowkey或row+col)Bloom Filter的优化都能生效,关键是get的类型要匹配Bloom Filter的类型
 
2.基于row的scan是没办法走Bloom Filter的。因为Bloom Filter是需要事先知道过滤项的。对于顺序scan是没有事先办法知道rowkey的。而get是指明了rowkey所以可以用Bloom Filter,scan指明column同理。
 
3.row+col+qualify的scan可以去掉不存在此qualify的storefile,也算是不错的优化了,而且指明qualify也能减少流量,因此scan尽量指明qualify。

HBase之八--(3):Hbase 布隆过滤器BloomFilter介绍的更多相关文章

  1. Hbase 布隆过滤器BloomFilter介绍

    转载自:http://blog.csdn.net/opensure/article/details/46453681 1.主要功能 提高随机读的性能 2.存储开销 bloom filter的数据存在S ...

  2. Spark布隆过滤器(bloomFilter)

    数据过滤在很多场景都会应用到,特别是在大数据环境下.在数据量很大的场景实现过滤或者全局去重,需要存储的数据量和计算代价是非常庞大的.很多小伙伴第一念头肯定会想到布隆过滤器,有一定的精度损失,但是存储性 ...

  3. 布隆过滤器(BloomFilter)持久化

    摘要 Bloomfilter运行在一台机器的内存上,不方便持久化(机器down掉就什么都没啦),也不方便分布式程序的统一去重.我们可以将数据进行持久化,这样就克服了down机的问题,常见的持久化方法包 ...

  4. 白话布隆过滤器BloomFilter

    通过本文将了解到以下内容: 查找问题的一般思路 布隆过滤器的基本原理 布隆过滤器的典型应用 布隆过滤器的工程实现 场景说明: 本文阐述的场景均为普通单机服务器.并非分布式大数据平台,因为在大数据平台下 ...

  5. 【浅析】|白话布隆过滤器BloomFilter

    通过本文将了解到以下内容: 查找问题的一般思路 布隆过滤器的基本原理 布隆过滤器的典型应用 布隆过滤器的工程实现 场景说明: 本文阐述的场景均为普通单机服务器.并非分布式大数据平台,因为在大数据平台下 ...

  6. 海量数据处理之布隆过滤器BloomFilter算法

    Bloom Filter是由Bloom在1970年提出的一种多哈希函数映射的快速查找算法.通常应用在一些需要快速判断某个元素是否属于集合,但是并不严格要求100%正确的场合.使用场景:数据量为100亿 ...

  7. 一道腾讯面试题:如何快速判断某 URL 是否在 20 亿的网址 URL 集合中?布隆过滤器

    何为布隆过滤器 还是以上面的例子为例: 判断逻辑: 多次哈希: Guava的BloomFilter 创建BloomFilter 最终还是调用: 使用: 算法特点 使用场景 假设遇到这样一个问题:一个网 ...

  8. python实现布隆过滤器及原理解析

    python实现布隆过滤器及原理解析     布隆过滤器( BloomFilter )是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地 ...

  9. Redis实现布隆过滤器解析

    布隆过滤器原理介绍 [1]概念说明 1)布隆过滤器(Bloom Filter)是1970年由布隆提出的.它实际上是一个很长的二进制向量和一系列随机映射函数.布隆过滤器可以用于检索一个元素是否在一个集合 ...

随机推荐

  1. 【Sizzle学习】之关于【初探 jQuery 的 Sizzle 选择器】这篇文章里的小bug

    [题记]不可否认,这篇文章写得非常好,但是今天我在看sizzle源码的时候,发现这文章有一地方说的不妥.重现:当selectors为"p.class1>p.class2",j ...

  2. PHP strip_tags() 函数的作用和用法

    strip_tags()函数可以轻松实现从字符串中去除 HTML 和 PHP 标记. 使用方法: trip_tags ( string $str [, string $allowable_tags ] ...

  3. 自定义控件-滑动条SeekBar

    一.效果图 二.实现思路 1.控件继承自View 2.重写两个方法onDraw() 绘制页面和 onTouch() 添加监听 3.onDraw(Canvas ca)中     a.new Canvas ...

  4. vim+ctags用法

    vim用法     在VIM编辑器的环境下用":make"就可以编译程序,如果程序中有错误,就会显示出来.          下列命令可以快速定位,并修改错误错误 ":c ...

  5. NAT&Port Forwarding&Port Triggering

    NAT     Nat,网络地址转换协议.主要功能是实现局域网内的本地主机与外网通信.     在连接外网时,内部Ip地址需要转换为网关(一般为路由器Ip地址)(端口号也需要相应的转换)     如: ...

  6. webpack 事件触发 按需加载

    比较易懂, 方法简单 var util_sync = require('./util-sync.js') alert(util_sync.data) document.getElementById(& ...

  7. c++下使用命名管道实现进程间通信

    前面已经使用邮槽实现过进程间通信:http://www.cnblogs.com/jzincnblogs/p/5192654.html ,这里使用命名管道实现进程间通信. 与邮槽不同的是,命名管道在进程 ...

  8. [置顶] 滴滴插件化VirtualAPK框架原理解析(二)之Service 管理

    在前一篇博客滴滴插件化框架VirtualAPK原理解析(一)之插件Activity管理 中VirtualAPK是如何对Activity进行管理的,本篇博客,我们继续来学习这个框架,这次我们学习的是如何 ...

  9. angular 与jQuery混用 大坑一

    由于angular是在真实dom加载之后,运行,所以jQuery操作dom时,要先于angular添加的元素(如,ng-repeat),所以常常会出现,元素错位,解决办法:添加一个透明的站位元素:

  10. 【Keras学习】常见问题与解答

    Keras FAQ:常见问题 如何引用Keras? 如果Keras对你的研究有帮助的话,请在你的文章中引用Keras.这里是一个使用BibTex的例子 @misc{chollet2015keras, ...