写流程:
![](https://i-blog.csdnimg.cn/blog_migrate/7d73fd0ed016528e251c3bbe8d3e91df.png)
1)Client先访问zookeeper,获取hbase:meta表位于哪个Region Server。
2)访问对应的Region Server,获取hbase:meta表,根据读请求的namespace:table/rowkey,查询出目标数据位于哪个Region Server中的哪 个Region中。并将该table的region信息以及meta表的位置信息缓存在客户端的meta cache,方便下次访问。
3)与目标Region Server进行通讯;
4)将数据顺序写入(追加)到WAL;
5)将数据写入对应的MemStore,数据会在MemStore进行排序;
6)向客户端发送ack;
7)等达到MemStore的刷写时机后,将数据刷写到HFile。
读流程
1,客户端请求ZK集群获取存储元数据信息的META表所在的机器
2 ,请求META表所在的机器,下载META表到客户端并缓存在本地
3, 客户端解析META表, 获取要读取的数据所在的RegionServer机器
4 ,请求RegionServe确定读取的数据在哪个region中
5, 先从内存对象中获取数据 , 如果没有再查看缓存区域 ,缓存中没有再去Hfile中读取数据 , 为了快速的确定数据在哪个Hfile中, HBASE引入了布隆过滤器
6, 如果数据是从Hfile中读取, 会将数据缓存在缓存区中再返回给客户端 , 以便下次查询的时候提高查询效率
经过:zk-META---RgionServer--region---内存--缓存----Hfile(布隆过滤器快速筛选)
Flush时机:
- Region级别-跨列族
Region内的其中一个MemStore大小达到阈值(hbase.hregion.memstore.flush.size),该Region所有MemStore一起发生Flush,输入磁盘。默认大小是128M !
- RegionServer级别
当一个RegionServer内的全部MemStore使用内存总量所占比例达到了阈值(hbase.regionserver.global.memstore.upperLimit),那么会一起按Region的MemStore用量降序排列flush,直到降低到阈值(hbase.regionserver.global.memstore.lowerLimit)以下。
另有一个新的参数hbase.regionserver.global.memstore.size,设定了一个RS内全部Memstore的总大小阈值,默认大小为Heap的40%,达到阈值以后就会阻塞更新请求,并开始RS级别的MemStore flush,和上述行为相同。
- HLog-WAL文件
当region server的WAL的log数量达到hbase.regionserver.max.logs,该server上多个region的MemStore会被刷写到磁盘(按照时间顺序),以降低WAL的大小。否则会导致故障恢复时间过长。
- 手动触发
通过HBase shell或Java Api手动触发MemStore flush
布隆过滤器
使用很少的空间来实现从大量文件中定位数据一定不再某些文件中 ,极可能在某些文件中
每次flush都会在表对应的文件夹中生成Hfile文件 , 可能一个表中的Hfile文件会很多 ,为了快速的确定数据在哪个Hfile中, HBASE引入了布隆过滤器!
![](https://i-blog.csdnimg.cn/blog_migrate/f1417f8e32322c6cc7bebaec921f2405.png)
如上图所示,布隆过滤器不能明确指出哪一个文件一定包含所查找的行键,布隆过滤器的结果有误差存在。当布隆过滤器判断文件中不包含对应的行时,这个答案是绝对正确的;但是,当布隆过滤器判断得到文件中包含对应行时,这个答案却有可能是错的。也就是说,HBase还是有可能加载了不必要的块。尽管如此,布隆过滤器还是可以帮助我们跳过一些明显不需要扫描的文件。另外,错误率可以通过调整布隆过滤器所占空间的大小来调整,通常设置错误率为1%。
需要注意的是,使用布隆过滤器,并不一定能立即提升个别的get操作性能,因为同一时间可能有多个客户端向HBase发送请求,当负载过大时,HBase的性能受限于读磁盘的效率。但是,使用了布隆过滤器之后,可以减少不必要的块加载,从而可以提高整个集群的吞吐率。并且,因为HBase加载的块数量少了,缓存波动也降低了,进而提高了读缓存的命中率。
布隆过滤器其实就是将目标数据经过布隆大哥自己写的hash算法,
这个算法是将
将一个8位比特位1的数据 也就是8个1(这个是比特位的1)(数量根据需要的成功率会有变化),
然后将每个比特位通过他的算法对应到一个长度位64k的二进制数组上(长度也随成功率自行调整) ,
例如
https://google.com/abc/d
通过布隆过滤器时
可以计算出8个位置
1 2 3 9 15 20 31 32(仅举例)
那么我们就将8个比特位分别插入到这些位置
例如下图
如果 hello ---> hashcode的值是 12 12位置是1 说明hello极大的可能存在
![](https://i-blog.csdnimg.cn/blog_migrate/d804143970a1c9774484fd32dac13393.png)
如果下次存在经过这个过滤器的时候, 8个比特位完全重复的, 那么大概率是已经通过一次这个过滤器了, 大概率不代表完全确定, 因为可能存在偶然结果, 但是我们可以通过适当增大二进制数组的长度, 来确保尽量可靠
Hbase之所以会用到这个布隆过滤器是因为, region server 的内存在很多情况下会自动将内存中的热数据写入到文件中, 时间一长会造成一个region目录/一个列族目录下存在多个文件, 而且这些个文件可能存在重复数据, 让我们查询数据的时候, 显然盲目遍历的去查找是不科学的, Hbase就选择在写入每个文件时, 同时通过了布隆过滤器, 也就是每个文件都有一个布隆过滤器的二进制数组, 所以当Hbase查询数据时, 它会去选择读取结果全部命中布隆过滤器二进制数组的对应的文件, 这样虽然不能保证100%, 但是最坏的结果也就是多读了几个文件, 相比遍历, 效率显著提高!