版权声明:本文为博主原创文章,未经博主允许不得转载。https://www.jianshu.com/p/8ff388759c61
关于HBase memstore flush流程之前已有文章介绍,本文主要对触发条件或方式进行展开介绍,便于日后出现问题时追溯原因。
概况来说,memstore flush的情况分为如下6种:
【1、Memstore级别】
Memstore大小达到上限(hbase.hregion.memstore.flush.size,memsotre默认大小128M)时,会触发memstore flush
【2、Region级别】
当一个region中所有memstore大小总和达到了上限(hbase.hregion.memstore.block.multiplier*hbase.hregion.memstore.flush.size,默认2*128M=256M),会触发memstore flush
有一种场景是hbase在写入数据发生阻塞,原因就是这种情况,region server会在写入时检查每个region中的memstore总大小是否超过了单个memstore默认大小的2倍(hbase.hregion.memstore.block.multiplier参数决定),如果超过了则会阻塞写操作,避免产生OOM。由于在flush时还会由compact/split等操作同时进行,因此整个flush过程会比较漫长,必须要等待memstore完全flush到磁盘才会结束,默认regionserver会睡眠hbase.server.thread.wakefrequency(默认10s),再检查memstore大小是不是低于阈值。
生产环境是难以接受10s的等待时间的,因此在无法改变flush过程的时候,可以通过调整如下两个参数来避免或减少region级别的flush。
hbase.hregion.memstore.block.multiplier=10(默认是2,当节点内存充足时可调大此值)
habse.server.thread.wakefrequency=100(默认时10000ms)
【3、Region Server级别】
一个regionserver上会有很多region,意味着大量的memstore,很有可能单个region并没有超过阈值,但regionserver整体的内存占用达到阈值。
当一个region server上所有region中memstore的大小总和达到了head内存的低水位上限(hbase.regionserver.global.memstore.lowerlimit*hbase_heapsize,heap内存的低水位线,默认0.35),会触发部分memstore的flush,flush顺序是按照memstore由大到小执行,先执行memstore最大region的flush操作,再执行次大的,循环执行直到总体memstore内存使用量低于heap*0.35,以降低阻塞全部写操作flush带来的影响;
而当一个region server上所有region中memstore的大小总和达到了heap内存的上限(hbase.regionserver.global.memstore.upperlimit*hbase_heapsize,heap内存的高水位线,默认0.4),会阻塞所有的写操作,将所有memstore都进行flush。
【4、WAL数量达到上限,region级别】
设计这个触发条件的初衷是为了在region server宕掉时,通过WAL恢复的时间不要太久。
WAL的最大值由hbase.regionserver.hlog.blocksize*hbase.regionserver.maxlogs决定。一旦达到这个值,memstroe flush就会被触发。
WAL数量触发的flush策略是找到最早的un-archived WAL文件,将其对应的Region进行flush。
值得一提的是,blocksize (128 mb) * hbase.regionserver.maxlogs大小与hbase.regionserver.global.memstore.upperLimit * HBASE_HEAPSIZE两者之间谁大谁小,个人觉得前者应小于后者,因为若大于后者的话,将会优先做region server级别的flush,阻塞所有写操作,而这个阻塞往往是分钟级别。但cloudera给出的建议是前者大小应略大于后者,以保证不会提前发生flush,这点有待商榷。
【5、定期自动flush】
Region Server在启动时会启动一个线程PeriodicMemStoreFlusher,该线程每隔habse.server.thread.wakefrequency(默认10s)会检查该regeion Server的全部在线Region,当满足以下条件将会触发flush:
memstore中最老记录的时间戳与当前时间的时间间隔超过配置值hbase.regionserver.optionalcacheflushinterval(默认1小时),如果是meta表的region则为5分钟。
如果该参数为0,即为关闭自动刷写。同时,为了避免同时提交的flush太多,会有3~23秒的随机延迟。
【6、数据更新达到阈值】
同样由PeriodicMemStoreFlusher探测,当最后一次flush后的变更次数超过hbase.regionserver.flush.per.changes(默认3千万),也会触发flush。
【7、手工flush】
在hbase shell中调用flush,可以对某张表或某个region进行flush:
flush 'tablename'或flush 'region name'
【X Flush过程】
主要包括三个阶段:
1、prepareFlush阶段
第一步是对memstore做一个snapshot,同时为防止其他线程更新memstore,这里会为加上一个排他锁,阻塞客户端的写操作,由于创建spnashot非常快,因此锁期间对客户影响甚微。
相应打印日志内容为:
……regionserver.HRegion: Started memstore flush for t1,,1413622522846.58fd75078b4a47b8c6a20705f23209b7., current region memstore size 168……
2、flushCache阶段
将上一阶段产生的快照持久化到hdfs上的一个hfile,存放位置为对应reion文件夹下的.tmp目录。
相应打印日志内容为:
……hbase.regionserver.DefaultStoreFlusher: Flushed, sequenceid=562745, memsize=130.9 M, hasBloomFilter=true, into tmp file hdfs://nameservice1/hbase/data/default/f_acct_idtfno_map/1f70d611178c72de82fa5493dbd0772b/.tmp/6e35b0fe71b34f23aa0694a471050f5a
3、commit阶段
将上一阶段产生的临时文件移动到对应的列族目录下,同时删除第一步的snapshot。
相应打印日志内容为:
……regionserver.HStore: Added hdfs://nameservice1/hbase/data/default/data/…