主要集中来看看把snapshot的KeyValue数据写入HFile部分。先来看看HFile的格式:

之前在读请求文章里已经介绍个HFile的这个格式。HFile要保证每个HBlock大小约为64KB,采用DataBlock多级索引和BloomFilter一级索引的方法来构成HFile结构。整个写过程比较简单,在循环里便利获取MemStore的snapshot的KeyValue数据,然后不断写DataBlock里,如果当前DataBlock的总大小超过64KB,则DataBlock就停止添加数据(设置了压缩会进行压缩处理),同时计算DataBlock的索引,并添加到内存中,另外如果开启了BloomFilter属性也要写入对应的BloomBlock,这个过程中会注意保存未压缩大小等FileInfo数据。
当所有的snapshot数据都写入完DataBlock中后,就要开始写入DataBlock的多级索引了。HBase会根据之前保存的索引计算多级索引的级数,如果索引数量不多,则有可能只有RootIndexBlock一个级别。同时也会根据RookIndexBlock获得MidKey的数据。最后就按照顺序写入FileInfo以及BloomFilter的索引,还有Trailer。
总结
HBase采用了MemStore把随机写变为顺序写,这样有助于提高读请求的效率。另外也为了避免数据丢失使用HLog来记录修改日志。在整个写过程中,使用了多种手段减轻了锁竞争,提高了线程吞吐量,也注意缩短锁获取的时间,尽可能地提高并发。通过利用MVCC也避免了读写请求之间的影响。