View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.regionserver;
19  
20  import java.io.IOException;
21  import java.util.List;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.hadoop.conf.Configuration;
26  import org.apache.hadoop.hbase.HConstants;
27  import org.apache.hadoop.hbase.HTableDescriptor;
28  import org.apache.hadoop.hbase.TableName;
29  import org.apache.hadoop.hbase.classification.InterfaceAudience;
30  
31  /**
32   * Split size is the number of regions that are on this server that all are
33   * of the same table, cubed, times 2x the region flush size OR the maximum
34   * region split size, whichever is smaller.
35   * <p>
36   * For example, if the flush size is 128MB, then after two flushes (256MB) we
37   * will split which will make two regions that will split when their size is
38   * {@code 2^3 * 128MB*2 = 2048MB}.
39   * <p>
40   * If one of these regions splits, then there are three regions and now the
41   * split size is {@code 3^3 * 128MB*2 = 6912MB}, and so on until we reach the configured
42   * maximum file size and then from there on out, we'll use that.
43   */
44  @InterfaceAudience.Private
45  public class IncreasingToUpperBoundRegionSplitPolicy extends ConstantSizeRegionSplitPolicy {
46  
47    private static final Log LOG = LogFactory.getLog(IncreasingToUpperBoundRegionSplitPolicy.class);
48    protected long initialSize;
49  
50    @Override
51    protected void configureForRegion(HRegion region) {
52      super.configureForRegion(region);
53      Configuration conf = getConf();
54      initialSize = conf.getLong("hbase.increasing.policy.initial.size", -1);
55      if (initialSize > 0) {
56        return;
57      }
58      HTableDescriptor desc = region.getTableDesc();
59      if (desc != null) {
60        initialSize = 2 * desc.getMemStoreFlushSize();
61      }
62      if (initialSize <= 0) {
63        initialSize = 2 * conf.getLong(HConstants.HREGION_MEMSTORE_FLUSH_SIZE,
64                                       HTableDescriptor.DEFAULT_MEMSTORE_FLUSH_SIZE);
65      }
66    }
67  
68    @Override
69    protected boolean shouldSplit() {
70      boolean force = region.shouldForceSplit();
71      boolean foundABigStore = false;
72      // Get count of regions that have the same common table as this.region
73      int tableRegionsCount = getCountOfCommonTableRegions();
74      // Get size to check
75      long sizeToCheck = getSizeToCheck(tableRegionsCount);
76  
77      for (Store store : region.getStores()) {
78        // If any of the stores is unable to split (eg they contain reference files)
79        // then don't split
80        if (!store.canSplit()) {
81          return false;
82        }
83  
84        // Mark if any store is big enough
85        long size = store.getSize();
86        if (size > sizeToCheck) {
87          LOG.debug("ShouldSplit because " + store.getColumnFamilyName() + " size=" + size
88                    + ", sizeToCheck=" + sizeToCheck + ", regionsWithCommonTable="
89                    + tableRegionsCount);
90          foundABigStore = true;
91        }
92      }
93  
94      return foundABigStore | force;
95    }
96  
97    /**
98     * @return Count of regions on this server that share the table this.region
99     * belongs to
100    */
101   private int getCountOfCommonTableRegions() {
102     RegionServerServices rss = region.getRegionServerServices();
103     // Can be null in tests
104     if (rss == null) {
105       return 0;
106     }
107     TableName tablename = region.getTableDesc().getTableName();
108     int tableRegionsCount = 0;
109     try {
110       List<Region> hri = rss.getOnlineRegions(tablename);
111       tableRegionsCount = hri == null || hri.isEmpty() ? 0 : hri.size();
112     } catch (IOException e) {
113       LOG.debug("Failed getOnlineRegions " + tablename, e);
114     }
115     return tableRegionsCount;
116   }
117 
118   /**
119    * @return Region max size or {@code count of regions cubed * 2 * flushsize},
120    * which ever is smaller; guard against there being zero regions on this server.
121    */
122   protected long getSizeToCheck(final int tableRegionsCount) {
123     // safety check for 100 to avoid numerical overflow in extreme cases
124     return tableRegionsCount == 0 || tableRegionsCount > 100
125                ? getDesiredMaxFileSize()
126                : Math.min(getDesiredMaxFileSize(),
127                           initialSize * tableRegionsCount * tableRegionsCount * tableRegionsCount);
128   }
129 }