HBase之Region上Spilt流程分析

来源:互联网 发布:指南针2017软件骗局 编辑:程序博客网 时间:2024/05/17 09:24

我们知道在MemStore达到阀值以后,会进行flushRegion操作. 那么在操作完成之后,会对HRegion进行检查,看是否HRegion是否已经达到阀值,如果已经达到阀值,则需要对HRegion进行split操作。

 

一 检测HRegion是否需要进行Split的流程分析

boolean shouldSplit = region.checkSplit() != null; 会进行Region的split检测:

1.1 如果是Meta表,我们不需要对Meta表的Region进行Split操作,所以返回false

1.2 如果该Region正处于Recovering状态,我们也不能对它进行Split操作

1.3 根据SplitPolicy#shouldSplit方法检测是否需要进行split:

#  Region是否需要强制split,如果需要强制split返回TRUE

# 遍历该HRegion所有store,如果某一个store上有文件存在引用,则返回FALSE;再判断store的大小是否大于检查点的大小,如果大于返回TRUE,否则FALSE

1.4 获取split point,并返回split point

1.5 如果满足split条件,则调用CompactSplitThread#requestSplit方法进行split流程

 

二 分析CompactSplitThread是如何进行split的?

2.1 首先判断当前HRegionServer的在线的HRegion的数量是否已经达到阀值,默认是1000,如果已经达到阀值,则不能进行split

 

2.2 获取split point作为分割点

 

2.3 执行SplitRequest线程, 创建SplitTransaction,给表上读锁,防止并发修改表的元数据,如果事务没准备好,则不能进行split

 

2.4 调用SplitTransaction#prepare,进行split之前的准备工作

# 检测HRegion是否能够split;split point是否为null;检测split point 是否个HRegion的start key相等或者HRegion根本就不包含这个split point

# 如果允许split,初始化两个子HRegionInfo

 

2.5 调用SplitTransaction#execute方法,执行split操作

 

2.6 调用createDaughters创建两个子的HRegion

 

2.7 调用stepsAfterPONR方法打开两个新建的HRegion

 

2.8 释放读锁

 

三 分析创建两个子的HRegion的流程-createDaughters

3.1 调用SplitTransactionCoordination#startSplitTransaction方法,创建临时的/hbase/region-in-transition/regionName znode节点,节点类型

RS_ZK_REQUEST_REGION_SPLIT

 

3.2 调用SplitTransactionCoordination#waitForSplitTransaction方法,等待HMaster将这个需要split操作的节点从PENDING_SPLIT转化为SPLITING,也就是不断轮询HMaster更换状态为RS_ZK_REGION_SPLITTING,让HMaster知道正在执行split操作

3.3 调用HRegionFileSystem# createSplitsDir创建.split文件目录

 

3.4 关闭当前的被切割的HRegion

# 调用waitForFlushesAndCompaCtions,等待进行中的MemStore的flush 和 compaction操作完成

# 查看该HRegion所有MemStore是否大于hbase.hregion.preclose.

flush.size,默认5MB.如果满足,则就进行flush

# 关闭每一个HStore, 不在服务于任何调用

 

3.5 调用splitStoreFiles,并行遍历每一个StoreFile,对于每一个StoreFile然后创建splitStoreFiles,调用其splitStoreFile方法创建两个

DaugtherA和DaugtherB 的reference 文件

 

3.6调用createDaughterRegionFromSplits方法,创建Daughter HRegion

# HRegionFileSystem#commitDaughterRegion(hri) 把临时目录.splits移到最终的目录/table/region下这样daughterRegion就和parent同级目录。

# 然后创建A和B两个HRegion对象

 

3.7 修改hbase:meta中对应的元数据信息

 

四 打开新的Region服务请求- stepsAfterPONR

4.1 调用openDaughters打开新的split之后的HRegion,创建对应的HStore,读取Reference(Reference文件有专门的Scanner和reader来限制读取对应HFile的范围),从所有HFile里读取最大的MemStoreTS、SequenceId。HRegion成功打开后,就更新hbase:meta表中A和B的location。然后根据每个HFile的MaxSequenceId进行replay WALEdit,就是把内容重新写入HStore的memstore。如果WALEdit的logNum里小于MaxSequenceId则表明已经写入HFile(每条记录对应一个SequenceId),就会跳过。然后会请求一个异步Major compact,从Reference生成真正的HFile

 

4.2 SplitTransactionCoordination#completeSplitTransaction:更新zk节点状态。在zk上之前创建的/hbase/region-in-transition/regionName节点的type改为RS_ZK_REGION_SPLIT,通知HMaster完成split操作

 

 

 

 

 

 

 

 

 

 

 

原创粉丝点击