region server的内存用于读写缓存主要有memstore和blockcache,其中memstore是写缓存。region server收的到写请求,实际上访问的是该server的region。每个region包含多个store,一个store对应着一个列族。每个store中又包含一个memstore和多个Hfile文件。memstore位于region server的主内存中,而HFiles被持久化到HDFS中。当region server处理写请求的时候,数据首先写入到memstore中去,然后当到达一定的阀值的时候,memstore中的数据会被flush到HFile中,此时的数据才完成持久化。
memstore flush机制
为了减少flush过程对读写的影响,HBase采用了类似于两阶段提交的方式,将整个flush过程分为三个阶段:
- prepare阶段:遍历当前region中的所有memstore,将memstore中当前数据集kvset做一个快照snapshot,然后再新建一个新的kvset。后期的所有写入操作都会写入新的kvset中,而整个flush阶段读操作会首先分别遍历kvset和snapshot,如果查找不到再会到HFile中查找。prepare阶段需要加一把updateLock对写请求阻塞,结束之后会释放该锁。因为此阶段没有任何费时操作,因此持锁时间很短。
- flush阶段:遍历所有memstore,将prepare阶段生成的snapshot持久化为临时文件,临时文件会统一放到目录.tmp下。这个过程因为涉及到磁盘IO操作,因此相对比较耗时。
- commit阶段:遍历所有的memstore,将flush阶段生成的临时文件移到指定的ColumnFamily目录下,针对HFile生成对应的storefile和Reader,把storefile添加到HStore的storefiles列表中,最后再清空prepare阶段生成的snapshot。
memstore刷新策略
当region中任意一个memstore的大小达到了上限(hbase.hregion.memstore.flush.size,默认为134217728即128MB),会触发这个region中所有的memstore刷新到磁盘。
region级别限制:当region中所有memstore的大小总和达到了上限(hbase.hregion.memstore.block.multiplier hbase.hregion.memstore.flush.size,默认 2 128M = 256M),会触发memstore刷新并阻塞数据更新的请求。
region Server级别限制:当一个region Server中所有memstore的大小总和达到了上限hbase.regionserver.global.memstore.upperLimit HBASE_HEAPSIZE,会触发部分memstore刷新。Flush顺序是按照memstore由大到小执行,先Flush memstore最大的region,再执行次大的,直至总体memstore内存使用量低于阈值hbase.regionserver.global.memstore.lowerLimit HBASE_HEAPSIZE。
当一个region Server中WAL数量达到上限hbase.regionserver.maxlogs时,包含最早的memstore的region会开始flush到磁盘,以减少WAL日志的数量。
HBase定期刷新memstore:周期为hbase.regionserver.optionalcacheflushinterval,默认值为3600000ms即1小时,通过这个参数来确保memstore不会长时间没有持久化。设置该值为0时可关闭自动刷新。
可以手动执行flush,通过{hbase_dir}/bin/hbase shell命令, flush ‘tablename’或者flush ‘region_name’分别对一个表或者一个region进行flush。
避免过度flush
当一个region中的memstore数量过大时,每次的flush无疑开销是巨大的,所以应该尽量避免同一张表中设计过多的列族。
避免表的热点现象发生,即多个Region集中分布在一个region server上,在设计Rowkey的时候尽量随机一点,使Region分布的均衡一点