HBase中MemStore的刷写触发机制

因为HBase的数据存储使用的是HDFS,而HDFS是不支持随机读写的,所以HBase的数据写入采用LSM算法。LSM算法一般会分内存和磁盘两部分存放数据,在HBase的实现中,内存部分称作MemStore,采用的是跳跃表实现,维护了一个有序的KeyValue集合,磁盘部分有0到多个内部KeyValue有序的HFile文件组成。这些HFile文件,就是一些机制的触发下,将内存中MemStore数据刷写到磁盘形成的(其中,有些HFile文件是通过一些小的HFile文件采用多路归并算法合并形成)。

如上图,一台RegionServer服务器上会管理着多个Region,一个Region中可能会有1到多个列族。在存储上,一个列族对应一个Store,而一个Store就包括了LSM中提到的MemStore和StoreFile(即HFile)两部分。需要注意的是:刷写的最小执行单元是 Region而不是单个MemStore。如果一个 HRegion 中 Memstore 过多,当执行flush时,有可能有些MemStore数据量占比很小,比如k级别,刷写的话也不会释放很多内存,却会产生很多小文件,这也是官方建议大家设计表时列族不要太多的原因。

触发MemStore刷写的机制大概分为:人为手动触发、HBase定时触发、HLog数量限制触发,其他事件触发(Compact、Split、Truncate等)、内存限制触发。其中内存限制触发细分为:MemStore级别限制触发、Region级别限制触发、RegionServer级别限制触发。

人为手动触发 通过 shell 命令 flush 'tablename'或者 flush ‘regionname’分别对整表所有region和具体一个Region进行flush。 HBase定时触发 HBase提供自动刷写机制,到达自动刷写的时间,也会触发MemStore flush。自动刷新的时间间隔由 hbase.regionserver.optionalcacheflushinterval(默认1小时)指定。需要注意的是,该机制处理是整个集群所有表的所有region,对生产读写,以及HDFS小文件等都有不利影响。如果设定为0,则关闭定时自动刷写。 HLog数量限制触发 当WAL文件的数量超过 hbase.regionserver.maxlogs,region会按照时间顺序依次进行刷写,直到WAL文件数量减小到该参数值以下(该属性名已经废弃,现无需手动设置,最大值为32)。 其他事件触发 在执行Region的合并、分裂、快照以及HFile的Compact等前会执行刷写。 MemStore级别内存限制触发 当某个Region中任意一个MemStore达到 hbase.hregion.memstore.flush.size参数值大小,就会触发该Region的刷写。 Region级别内存限制触发 当某个Region中所有MemStore的大小加和达到了 hbase.hregion.memstore.block.multiplier*hbase.hregion.memstore.flush.size 值大小,就会触发该Region的刷写。此时会阻塞入该 Region 的写请求,如果往 MemStore 写数据,会出现 RegionTooBusyException 异常。 RegionServer级别内存限制触发 当某RegionServer种所有MemStore的大小加和达到了RegionServer全局低水位阈值 java_heapsize *hbase.regionserver.global.memstore.size*hbase.regionserver.global.memstore.size.lower.limit 值大小,RegionServer会强制执行刷写,按序选择Region所有包含MemStore大小加和大的Region执行。于此相关的,如果此时数据写入吞吐量依然很大,导致该RegionServer种所有MemStore的大小加和超过该RegionServer全局水位阈值 java_heapsize * hbase.regionserver.global.memstore.size 值大小,RegionServer会阻塞写请求,直到MemStore刷写大小将到低水位阈值。