RegionServer启动的时候初始化 CompactSplitThread
split 初始化。 ps:splitThreads 默认为1
this.splits = (ThreadPoolExecutor)
Executors.newFixedThreadPool(splitThreads,
new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName(n + "-splits-" + System.currentTimeMillis());
return t;
}
});
split 触发
1、 flushRegion的时候、检查是否需要split
2、执行完 compact 的时候
split 触发级别
api 手动 和 系统触发自动
出发后执行过程
1、 判断maxRegion 是否已经超过在线的 Region数量,是则退回
2、判断改region下的所有store中的最小优先级, 优先级的算法为 hbase.hstore.blockingStoreFiles - 目前Region 中 storeFile ,如果大于等于1 则执行(也就是说目前HFile的数量还没达到阻塞阀值),反则退回
3、判断storeFile是否需要split
计算当前RS 上面的同一个Table的 region数量 例如:x
获取memstoreflushsize ,例如 :y
则split 触发情况就是: min( x*x*x *y*2 ,MaxSplitSize);
也就说如果flushsize设置为 256M的话, 现在某RS上面就一个Region, 则 第一次split 为 512 ,当RS增加到2个时,触发的大小即为 8*512=4096,当RS增加到3个的时候触发大小为 9216 。 如果我们设置MaxSplitSize为10G,这也就是说当每个RS上面存在3个region的时候、再分裂就是按照MaxSplitSize大小来分裂。
4、获取分割点:
获取 Region 中最大的Store,然后循环Store 下面的 StoreFiles,找到最大的StoreFile。 StoreFile 是有多个Block组成,通过 DataBlockIndexReader 获取中间的block,然后取该 block 的第一个rowkey作为 SplitPoint 。
5 、 执行 SplitRequest 线程
首先split的触发条件是某一个storeFile的大小超过以下值时:
计算当前RS 上面的同一个Table的 region数量 例如:x
获取memstoreflushsize ,例如 :y
则split 触发情况就是: min( x*x*x *y*2 ,MaxSplitSize);
也就说如果flushsize设置为 256M的话, 现在某RS上面就一个Region, 则 第一次split 为 512 ,当RS增加到2个时,触发的大小即为 8*512=4096,当RS增加到3个的时候触发大小为 9216 。 如果我们设置MaxSplitSize为10G,这也就是说当每个RS上面存在3个region的时候、再分裂就是按照MaxSplitSize大小来分裂。
------------------------接下来具体讲解分裂---------------
通过上面条件查找出大的storeFile 然后获取大的storeFile的 midkey 也即splitPoint ,如果发现midkey 等于 firstkey 等于lastkey则不处理。
获取到splitkey之后、会有一个线程池中执行SplitRequest 线程
SplitRequest 主要执行: 封装SplitTransaction 主要用于事务控制,主要有 prepare execute rollback 三部分
prepare 1、 通过检查region没有关闭和没有引用文件 2、通过splitpoint 建立两个新region 、新region的regionId 为当前时间,regionName 即 start - plitpoint - regionId 等信息组成。
execute 1、在zk的 unsigned 节点下面新建临时节点
2、在SplitTransaction 中有一个枚举类JournalEntry 很不错, SplitTransaction 中有个JournalEntry 记录每一步骤,首先设置SET_SPLITTING_IN_ZK
3、在splits下面建立分裂目录
4、关闭要分裂的region , 获得region的 writestate 锁,如果当前region正在 compacting 或者 flushing 等待flushes 和 compactions 完成, 如果当前memstore的大小超过 hbase.hregion.preclose.flush.size (默认5M) 执行flush操作(internalFlushcache),把当前region 的closing 设置为true,获得writeLock锁,