第六章 HBase读写流程
6.1HBase写流程
6.1.1写入流程的三个阶段
整体架构视角,写流程可分为三个阶段
(1)客户端处理阶段
客户端将用户的写入请求进行预处理,根据集群的元数据定位写入数据所在的RegionServer,将请求发送给对应的RegionServer。
①步骤1
用户提交put请求,客户端先把写入的数据缓添加到本地缓存区(默认2M),超过阈值,异步批量提交。
②步骤2
寻找提交数据的RegionServer
客户端 访问 zk 上/hbase-root/meta-region-server节点 查找hbase:meta元数据表所在的RegioServer;
向hbase:meta元数据表所在的RegioServer 发送查询请求,查询写入数据rowkey 所在的RegionServer 和 Region信息。
缓存查询结果,以便下次使用;
客户端请写入请求发给目标RegionServer。
③步骤3
Hbase构造一个远程RPC请求MultiServerCallable,将请求序列化后发给目标RegionServer
(2)Region写入阶段
RegionServer收到请求后,解析数据(反序列化为put对象),首先写入WAL,再写入对应Region 列族的MemStore。
抽象为两步: 追加写入Hlog ; 随机写入MemStore
(3)MemStore Flush阶段
当Region中的MemStore容量超过一定阈值,就开始异步刷写flush操作,将内存数据写入文件,形成Hfile
6.1.3 MemStore Flush (一个Region 多个Store,一个Store 一个MemStore)
触发条件
MemStore级别限制:
当Region中任意一个MemStore的大小达到了上限(hbase.hregion.memstore.flush.size,默认128MB),会触发MemStore刷新。
Region级别限制:
当Region中所有MemStore的大小总和达到了上限(hbase.hregion. memstore.block.multiplier * hbase.hregion.memstore.flush.size),会触发MemStore刷新。
RegionServer级别限制:
当RegionServer中MemStore的大小总和超过低水位阈值hbase.regionserver.global.memstore.size.lower.limit * hbase.regionserver.global.memstore.size,
RegionServer开始强制执行flush,先flush MemStore最大的Region,再flush次大的,依次执行。
如果此时写入吞吐量依然很高,导致总MemStore大小超过高水位阈值hbase.regionserver.global.memstore.size,
RegionServer会阻塞更新并强制执行flush,直至总MemStore大小下降到低水位阈值。
当一个RegionServer中HLog数量达到上限
(可通过参数hbase.regionserver.maxlogs配置)时,系统会选取最早的HLog对应的一个或多个Region进行flush。
HBase定期刷新MemStore
默认周期为1小时,确保MemStore不会长时间没有持久化。
为避免所有的MemStore在同一时间都进行flush而导致的问题,定期的flush操作有一定时间的随机延时。
手动执行flush :
用户可以通过shell命令flush 'tablename'或者flush 'regionname'分别对一个表或者一个Region进行flush。
6.3 Hbase读数据流程
读流程从头到尾可以分为如下4个步骤:
Client-Server读取交互逻辑
Server端Scan框架体系
过滤淘汰不符合查询条件的HFile
从HFile中读取待查找Key
其中,过滤手段主要有三种:根据KeyRange过滤,根据TimeRange过滤,根据布隆过滤器进行过滤。
【讲的太详细了,从底层源码角度分析】
【个人总结】
1)Client先访问zookeeper,从meta表读取region的位置,然后读取meta表中的数据。meta中又存储了用户表的region信息;
2)根据namespace、表名和rowkey在meta表中找到对应的region信息;
3)找到这个region对应的regionserver;
4)查找对应的region;
5)先从MemStore找数据,如果没有,再到BlockCache里面读;
6)BlockCache还没有,再到HFile上读(为了读取的效率);
7)如果是从HFile里面读取的数据,不是直接返回给客户端,而是先写入BlockCache,再返回给客户端。