Hbase Cell实现类-KeyValue

KeyValue是cell最重要的实现类。

Hbase Cell实现类-KeyValue

一个KeyValue类里面最后一个部分是存储数据的Value,前面部分都是存储跟cell相关的元数据信息。如果value很小,那么这个cell的绝大部分空间就是rowkey、column family、column等元数据,所有如果列族和列的名字很长,大部分空间都用来存储这些数据了。
采用适当的压缩算法可以极大的节省存储列族、列等信息的空间。但是压缩和解压必然带来性能损耗,所以使用压缩需要根据实际情况来取舍。


KeyValue写入和读取

写入

一个KeyValue被持久化到HDFS的过程总结如下

Hbase Cell实现类-KeyValue

  1. WAL:数据被发出之后第一时间被写入WAL。由于WAL是基于HDFS来实现的,所以也可以说现在cell就已经被持久化了,但是WAL只是一个暂存的日志,它是不区分Store的。这些数据是不能被直接读取和使用
  2. Memstore:数据随后会立即被放入Memstore中进行整理。Memstore会负责按照LSM树的结构来存放数据。这个过程就像我们在打牌的时候,抓牌之后在手上对牌进行整理的过程。
  3. HFile:最后当Memstore到达一定的大小阈值,或者达到了刷写时间间隔阀值的时候,HBaes会把这个Memstore的内容刷写到HDFS上一个新的HFile文件。至此数据真正地被持久化到硬盘上,就算宕机、断电数据也不会丢失了。

读出

HBase在处理读取的时候实际的读取顺序是先从BlockCache中找数据,找不到了再去Memstore和HFile中查询数据。

由于HDFS的文件不可变特性,不可能在一个KeyValue被新建之后删除它,HBase所能做的也就是给要删除的KeyValue加上一个墓碑标记。但是HDFS是不能修改的,数据被写入的时候都是充分地占用了空间,没有位置可以写入墓碑标记了,因此墓碑数据和真实数据不在一个地方

疑问:墓碑标记和数据不在一个地方了,那读取数据的时候怎么知道这个数据要删除呢???

如果这个数据比它的墓碑标记更早被读到,那在这个时间点是不知道这个数据会被删除的,只有当扫描器接着往下读,读到墓碑标记的时候才知道这个数据是被标记为删除的,不需要返回给用户。所以HBase的Scan操作在取到所需要的所有行键对应的信息之后还会继续扫描下去,直到被扫描的数据大于给出的限定条件为止,这样它才能知道哪些数据应该被返回给用户,而哪些应该被舍弃。所以增加过滤条件也无法减少Scan遍历的行数,只有缩小STARTROW和ENDROW之间的行键范围才可以明显地加快扫描的速度。

在Scan扫描的时候store会创建StoreScanner实例。StoreScanner会把MemStore和HFile结合起来扫描,所以具体从MemStore还是HFile中读取数据,外部的调用者都不需要知道具体的细节。当StoreScanner打开的时候,会先定位到起始行键(STARTROW)上,然后开始往下扫描。所以读取数据的归纳如下图所示:

Hbase Cell实现类-KeyValue

其中红色块部分都是属于指定row的数据,Scan要把所有符合条件的StoreScanner都扫描过一遍之后才会返回数据给用户。


《Hbase不睡觉》读书笔记