001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.regionserver; 019 020import java.util.Random; 021 022import org.apache.hadoop.conf.Configuration; 023import org.apache.hadoop.hbase.HBaseInterfaceAudience; 024import org.apache.hadoop.hbase.HConstants; 025import org.apache.yetus.audience.InterfaceAudience; 026import org.apache.hadoop.hbase.client.TableDescriptor; 027import org.apache.hadoop.hbase.procedure2.util.StringUtils; 028import org.slf4j.Logger; 029import org.slf4j.LoggerFactory; 030 031/** 032 * A {@link RegionSplitPolicy} implementation which splits a region 033 * as soon as any of its store files exceeds a maximum configurable 034 * size. 035 * <p> 036 * This is the default split policy. From 0.94.0 on the default split policy has 037 * changed to {@link IncreasingToUpperBoundRegionSplitPolicy} 038 * </p> 039 */ 040@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG) 041public class ConstantSizeRegionSplitPolicy extends RegionSplitPolicy { 042 private static final Logger LOG = 043 LoggerFactory.getLogger(ConstantSizeRegionSplitPolicy.class); 044 private static final Random RANDOM = new Random(); 045 046 private long desiredMaxFileSize; 047 private double jitterRate; 048 protected boolean overallHRegionFiles; 049 050 @Override 051 protected void configureForRegion(HRegion region) { 052 super.configureForRegion(region); 053 Configuration conf = getConf(); 054 TableDescriptor desc = region.getTableDescriptor(); 055 if (desc != null) { 056 this.desiredMaxFileSize = desc.getMaxFileSize(); 057 } 058 if (this.desiredMaxFileSize <= 0) { 059 this.desiredMaxFileSize = conf.getLong(HConstants.HREGION_MAX_FILESIZE, 060 HConstants.DEFAULT_MAX_FILE_SIZE); 061 } 062 this.overallHRegionFiles = conf.getBoolean(HConstants.OVERALL_HREGION_FILES, 063 HConstants.DEFAULT_OVERALL_HREGION_FILES); 064 double jitter = conf.getDouble("hbase.hregion.max.filesize.jitter", 0.25D); 065 this.jitterRate = (RANDOM.nextFloat() - 0.5D) * jitter; 066 long jitterValue = (long) (this.desiredMaxFileSize * this.jitterRate); 067 // make sure the long value won't overflow with jitter 068 if (this.jitterRate > 0 && jitterValue > (Long.MAX_VALUE - this.desiredMaxFileSize)) { 069 this.desiredMaxFileSize = Long.MAX_VALUE; 070 } else { 071 this.desiredMaxFileSize += jitterValue; 072 } 073 } 074 075 @Override 076 protected boolean shouldSplit() { 077 if (!canSplit()) { 078 return false; 079 } 080 return isExceedSize(desiredMaxFileSize); 081 } 082 083 long getDesiredMaxFileSize() { 084 return desiredMaxFileSize; 085 } 086 087 @InterfaceAudience.Private 088 public boolean positiveJitterRate() { 089 return this.jitterRate > 0; 090 } 091 092 /** 093 * @return true if region size exceed the sizeToCheck 094 */ 095 protected final boolean isExceedSize(long sizeToCheck) { 096 if (overallHRegionFiles) { 097 long sumSize = 0; 098 for (HStore store : region.getStores()) { 099 sumSize += store.getSize(); 100 } 101 if (sumSize > sizeToCheck) { 102 LOG.debug("ShouldSplit because region size is big enough " 103 + "size={}, sizeToCheck={}{}", StringUtils.humanSize(sumSize), 104 StringUtils.humanSize(sizeToCheck)); 105 return true; 106 } 107 } else { 108 for (HStore store : region.getStores()) { 109 long size = store.getSize(); 110 if (size > sizeToCheck) { 111 LOG.debug("ShouldSplit because {} size={}, sizeToCheck={}{}", 112 store.getColumnFamilyName(), StringUtils.humanSize(size), 113 StringUtils.humanSize(sizeToCheck)); 114 return true; 115 } 116 } 117 } 118 return false; 119 } 120}