一条数据的HBase之旅,简明HBase入门教程11:In-Memory Flush
在2.0版本中,Flush的行为发生了变化,默认的Flush,仅仅是将正在写的MemStore中的数据归档成一个不可变的Segment,而这个Segment依然处于内存中,这就是2.0的新特性:In-memory Flush and Compaction ,而且该特性在2.0版本中已被默认启用(系统表除外)。
上文中简单提到了MemStore的核心是一个CellSet,但到了这里,我们可以发现,MemStore的结构其实更加复杂:MemStore由一个可写的Segment,以及一个或多个不可写的Segments构成。
MemStore中的数据先Flush成一个Immutable的Segment,多个Immutable Segments可以在内存中进行Compaction,当达到一定阈值以后才将内存中的数据持久化成HDFS中的HFile文件。
看到这里,可能会有这样的疑问:这样做的好处是什么?为何不直接调大MemStore的Flush Size?
如果MemStore中的数据被直接Flush成HFile,而多个HFile又被Compaction合并成了一个大问题,随着一次次Compaction发生以后,一条数据往往被重写了多次,这带来显著的IO放大问题,另外,频繁的Compaction对IO资源的竞争,其实也是导致HBase查询时延大毛刺的罪魁祸首之一。而In-memory Flush and Compaction特性可以有力改善这一问题。
那为何不干脆调大MemStore的大小?这里的本质原因在于,ConcurrentSkipListMap在存储的数据量达到一定大小以后,写入性能将会出现显著的恶化。
在融入了In-Memory Flush and Compaction特性之后,Flush与Compaction的整体流程演变为:
关于Flush执行的策略:
一个Region中是否执行Flush,原来的默认行为是通过计算Region中所有Column Family的整体大小,如果超过了一个阈值,则这个Region中所有的Column Family都会被执行Flush。
2.0版本中合入了0.89-fb版本中的一个特性:HBASE-10201/HBASE-3149:Make flush decisions per column family。
而2.0版本中默认启用的Flush策略为FlushAllLargeStoresPolicy,也就是说,这个策略使得每一次只Flush超出阈值大小的Column Family,如果都未超出大小,则所有的Column Family都会被Flush。
改动之前,一个Region中所有的Column Family的Flush都是同步的,虽然容易导致大量的小HFile,但也有好处,尤其是对于WAL文件的快速老化,避免导致过多的WAL文件。而如果这些Column Family的Flush不同步以后,可能会导致过多的WAL文件(过多的WAL文件会触发一些拥有老数据的Column Family执行Flush),这里需要结合业务场景实测一下。如果每一行数据的写入,多个Column Family的数据都是同步写入的,那么,这个默认策略可能并不合适。
- 点赞
- 收藏
- 关注作者
评论(0)