region split流程分析
splitregion的发起主要通过client端调用regionserver.splitRegion或memstore.flsuh时检查并发起。
Client通过rpc调用regionserver的splitRegion方法
client端通过HBaseAdmin.split传入regionname与splitpoint(切分的rowkey,可以不传入),
通过meta得到此region所在的server,发起rpc请求,调用HRegionServer.splitRegion方法
publicSplitRegionResponse splitRegion(finalRpcController controller,
finalSplitRegionRequest request)throwsServiceException {
try{
checkOpen();
requestCount.increment();
从onlineRegions中拿到对应的HRegion
HRegion region= getRegion(request.getRegion());
region.startRegionOperation(Operation.SPLIT_REGION);
LOG.info("Splitting" +region.getRegionNameAsString());
在做split前,先对region进行flush操作。请参见regionflush流程分析
region.flushcache();
如果client端发起split请求时指定有split的rowkey,拿到splitkey的值
byte[]splitPoint= null;
if(request.hasSplitPoint()){
splitPoint= request.getSplitPoint().toByteArray();
}
设置region的splitRequest属性为true,表示有splitrequest
如果splitrowkey传入不为空,也就是指定有rowkey,设置region的explicitSplitPoint为指定的rowkey
但此值设置后不会被清空,原因后面分析
region.forceSplit(splitPoint);
发起splitrequest,到split的线程进行处理。
Region.checkSplit流程:
a.检查region是否是meta/namespace的region,如果是返回null
b.如果hbase.master.distributed.log.replay配置为true时,同时openRegion后此region还没有被replay
region.isRecovering==true,如果是返回null
c.通过hbase.regionserver.region.split.policy配置的RegionSplitPolicy,
默认为IncreasingToUpperBoundRegionSplitPolicy,
也可以直接在tablecreate时配置SPLIT_POLICY的值为class
调用splitPolicy.shouldSplit(),此方法做如下检查流程,并返回true与false
c.1检查region.splitRequest的值是否为true,如果是,返回true,
c.2得到当前regionserver中此region对应的table的所有region个数,
得到region的存储最大size,
c.2.1取出通过tablecreate时的属性MAX_FILESIZE来设置的region最大存储大小,
如果没有取hbase.hregion.max.filesize配置的的值,默认为10* 1024 * 1024 * 1024L(10g)
c.2.2取出通过tablecreate时的MEMSTORE_FLUSHSIZE属性来设置的regionmemstore的大小,
如果没有取hbase.hregion.memstore.flush.size配置的值,默认为1024*1024*128L(128M)
c.2.3通过c.2.2的值*(当前rs中此table的region个数*当前rs中此table的region个数)
c.2.4取出c.2.1中得到的值与c.2.3计算出的值最小的一个,得到region最大可存储的size值
c.3检查region中所有store中是否有reference的storefile,如果有返回false
c.4检查region