一  HRegionServer启动的时候,会调用startServiceThreads,启动一些后台线程,比如compact checker,启动flushCache等线程

 

二HRegionServer启动后台线程的时候,会通过MemStoreFlusher

#start方法,开启FlushHandler线程.

 

三 只要RegionServer一直运行,FlushHandler就一直运行,然后不断从flushQueue当中poll出队首的FlushRegionEntry元素,这个FlushRegionEntry其实就是持有HRegion和重试次数的一个对象

 

四 然后调用flushRegion(FlushQueueEntry)方法

首先会判断Region是否是Meta Region,并且判断这Region是否有太多的StoreFiles,如果StoreFiles 数量太多:

# 如果不要split,则就进行compact操作

# FlushRegionEntry需要重新放入flushQueue,后面再执行,然后返回

其次:如果Region没有很多的StoreFiles,或者还没有达到阀值

那么这时候才开始flush region,调用HRegion#flushCache方法

然后:如果该Region已经下线,则直接返回

接着:会调用到internalFlushCache方法,这才是真正的开始flush

Cache。

流程如下:

# 如果没有可以刷新的缓存,返回,但是需要更新Region的sequence id。

# 获取该Region的更新锁的写锁,阻塞所有对该Region的更新操作

# 如果WAL不能进行flush cache,则返回

# 开始刷新前准备工作:从MemStore获取快照;从快照获取单元格数量;获取MemStore的大小

# 将数据写入文件

# 进行提交操作,主要是更新StoreFile信息,以判断是否需要compaction

# 重新设置flush之后,MemStore的大小

# 无论如何,始终都会返回一个FlushResult对象:封装的是flush有没有成功,成功之后,是否需要触发compact和split操作之类的

紧接着:根据FlushResult判断是否应该compact,是否需要split?

如果需要split,则触发split操作;否则如果需要触发compact操作则进行compact操作

 

 

 

 

 

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。