Hbase的读写流程深度解析
当我们在对HBase的读写操作时,都需要提前知道我们需要操作的region的所在位置,即是存在于哪个HRegionServer上,因此在HBase中存在一张表元数据表.meta表(属于Hbase的内置表)专门存储了表的元数据信息,以及region位于哪个regionserver上。
.meta表的结构类似于下图:
.meta表的RowKey由三部分组成:TableName(表名)、StartKey(起始键)、TimeStamp(时间戳),rowkey存储的内容又称为region的Name(扩展:用来存放Region的文件夹的名字为RegionName的hash值,因为某些RegionName包含某些非法字符,而RegionName为什么会包含非法字符是因为startkey是允许包含任何值的)。将组成rowkey的三个部分用逗号隔开组成了整个完整的rowkey。TimeStamp使用十进制的数字字符串来表示。
.meta表的info为表中最主要的列簇,含有三个column:regioninfo、server、serverstartcode。regioninfo存储的是region的详细信息,包括startkey、endkey、以及每个family信息。server存储的是管理这个region的regionserver地址。
由于.meta存储的是region的信息,如果当hbase中表的数据非常大会被分成很多个region,那么此时在.meta中所占的空间也会变大,而.meta本身也是一张表,在存储数据非常大的情况下,也会被分割成多个region存储于不同的regionserver上,此时要是想把.meta表的region位置信息存储在zookeeper集群中就不太现实,.meta表region的位置信息是会发生变化的。因此,此时我们可以通过另外一张表来存储.meta表的元数据信息,即-ROOT-(根数据表),hbase认为这张表不会太大,因此-ROOT-只会有一个region,这个region的信息存在于hbase中,而管理-ROOT-表的位置信息(regionserver地址)存储在Zookeeper中。
ROOT表结构类似和.meta表一样,具体如下所示
所以综上所述要想对HBase进行读写首先去访问Zookeeper集群,获得ROOT表的所在regionserver地址信息。
具体读写操作如下所示
写操作
- Client访问Zookeeper集群,查询ROOT表region所在的regionserver地址信息,比如rs1;
- client连接rs1,访问ROOT表,根据写入信息查询.meta表的region位于哪些regionserver上,将得到的结果返回给client;
- client去连接相应的rs,访问.meta表,根据写入的namespace、表名和rowkey找到对应的region信息;
- client连接最终的rs,为了持久化和恢复,将数据先写到Hlog(write ahead log)中;
- 在将数据写入到memstore中,当memstore达到预设阈值后,就会创建一个新的memstore,而老的memstore就会加入flush队列,由单独的线程flush到磁盘上,形成一个storefile;
- 与此同时,系统会在Zookeeper记录一个checkpoint,表示这个时刻之前的数据变更已经持久化了,当系统出现意外可能导致memstore中的数据丢失,就可以通过hlog来恢复checkpoint之后的数据;
- 每次flush就会形成一个storefile文件,而storefile文件是只读的,一旦创建之后就不可修改,因此hbase的更新就是不断追加的操作;
- 随着storefile的数量不断增多,当达到设定阈值后就会触发compact合并操作,将多个storefile合并成一个大的storefile,同时进行版本合并和数据删除;
- 当store中的单个storefile文件的大小超过阈值的时候,触发split操作,regionserver把当前的region split成2个新的region;
- 父region就会下线,新split出的2个region就会被hmaster分配到两个regionserver上,实现负载均衡,使得原先一个region的压力分流到两个region上。
读操作
- client访问Zookeeper中,找到ROOT表的Region所在的RegionServer信息;
- client连接RegionServer访问ROOT表查询.meta表的region位置信息;
- 再去连接.meta表的region所在的regionserver然后访问meta表,找到目标数据在哪个region上,及region所在的regionserver位置信息;
- 然后去访问目标数据所在的regionserver中的region,先在memstore中查询数据,memstore中不存在则在BlockCache中读数据,BlockCache中还是不存在的话就最后在storefile中读数据,并且将读取到的数据先写入到BlockCache中,然后再返回给客户端。
参考链接:
https://blog.csdn.net/ldds_520/article/details/51674315
https://blog.csdn.net/u011833033/article/details/79773421