MemStore上,MemStore超过阀值,HRegion就会请求把MemStore的数据flush到HDFS上。另外要注意到的是,这里flush的单位是单个HRegion,也就是说如果有多个HStore,只要有一个MemStore超过阀值,这个HRegion所属的所有HStore都要执行flush操作。 HRegion首先要获取updatesLock的写锁,这样就防止有新的写请求到来请求获取MVCC的写序号请求MemStore生成snapshot释放updatesLock的写锁提交之前获取的MVCC写序号,等待之前的事务完成,防止回滚事务写入HFile把snapshot的KeyValue数据写入到HFile里
主要集中来看看把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也避免了读写请求之间的影响。