From 422e78ceab5436f5efafee6a9fd5e3a0c5bf9f52 Mon Sep 17 00:00:00 2001 From: Esteban Gutierrez Date: Tue, 9 Jun 2015 14:58:18 -0700 Subject: [PATCH] HBASE-13874 Fix 0.8 being hardcoded sum of blockcache + memstore; doesn't make sense when big heap --- .../java/org/apache/hadoop/hbase/HConstants.java | 4 ++- .../hadoop/hbase/io/util/HeapMemorySizeUtil.java | 19 ++++++++--- hbase-common/src/main/resources/hbase-default.xml | 8 +++++ .../hbase/regionserver/HeapMemoryManager.java | 39 +++++++++++++--------- 4 files changed, 48 insertions(+), 22 deletions(-) diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java index 674ef6e..7a879ff 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java @@ -847,7 +847,9 @@ public final class HConstants { /* * Minimum percentage of free heap necessary for a successful cluster startup. */ - public static final float HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD = 0.2f; + public static final String HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD_KEY = + "hbase.regionserver.reserved.memory.threshold"; + public static final float HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD_DEFAULT = 0.2f; public static final Pattern CP_HTD_ATTR_KEY_PATTERN = Pattern.compile ("^coprocessor\\$([0-9]+)$", Pattern.CASE_INSENSITIVE); diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/util/HeapMemorySizeUtil.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/util/HeapMemorySizeUtil.java index 7cfa35d..5d82df8 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/util/HeapMemorySizeUtil.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/util/HeapMemorySizeUtil.java @@ -26,6 +26,9 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.classification.InterfaceAudience; +import static org.apache.hadoop.hbase.HConstants.HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD_DEFAULT; +import static org.apache.hadoop.hbase.HConstants.HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD_KEY; + @InterfaceAudience.Private public class HeapMemorySizeUtil { @@ -58,12 +61,15 @@ public class HeapMemorySizeUtil { int gml = (int)(globalMemstoreSize * CONVERT_TO_PERCENTAGE); float blockCacheUpperLimit = getBlockCacheHeapPercent(conf); int bcul = (int)(blockCacheUpperLimit * CONVERT_TO_PERCENTAGE); + float minimumMemoryThreshold = 1 - conf.getFloat(HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD_KEY, + HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD_DEFAULT); if (CONVERT_TO_PERCENTAGE - (gml + bcul) - < (int)(CONVERT_TO_PERCENTAGE * - HConstants.HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD)) { + < (int)(CONVERT_TO_PERCENTAGE * minimumMemoryThreshold)) { throw new RuntimeException("Current heap configuration for MemStore and BlockCache exceeds " + "the threshold required for successful cluster operation. " - + "The combined value cannot exceed 0.8. Please check " + + "The combined value cannot exceed " + + String.format("%.1f", minimumMemoryThreshold) + + ". Please check " + "the settings for hbase.regionserver.global.memstore.size and " + "hfile.block.cache.size in your configuration. " + "hbase.regionserver.global.memstore.size is " + globalMemstoreSize @@ -79,10 +85,13 @@ public class HeapMemorySizeUtil { public static float getGlobalMemStorePercent(final Configuration c, final boolean logInvalid) { float limit = c.getFloat(MEMSTORE_SIZE_KEY, c.getFloat(MEMSTORE_SIZE_OLD_KEY, DEFAULT_MEMSTORE_SIZE)); - if (limit > 0.8f || limit <= 0.0f) { + float clusterMinimumMemoryThreshold = c.getFloat(HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD_KEY, + HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD_DEFAULT); + if (limit > clusterMinimumMemoryThreshold || limit <= 0.0f) { if (logInvalid) { LOG.warn("Setting global memstore limit to default of " + DEFAULT_MEMSTORE_SIZE - + " because supplied value outside allowed range of (0 -> 0.8]"); + + " because supplied value outside allowed range of (0 -> " + + "]"); } limit = DEFAULT_MEMSTORE_SIZE; } diff --git a/hbase-common/src/main/resources/hbase-default.xml b/hbase-common/src/main/resources/hbase-default.xml index 9a4baf5..40cc8ee 100644 --- a/hbase-common/src/main/resources/hbase-default.xml +++ b/hbase-common/src/main/resources/hbase-default.xml @@ -295,6 +295,14 @@ possible configurations would overwhelm and obscure the important. + hbase.regionserver.reserved.memory.threshold + 0.2 + Minimum percentage of memory that the region server should reserve for + normal operation. This value is usually 20% of the configured heap, but as larger + heap sizes are configured it is possible to lower this threshold in order to use more + resources for the memstores or the block cache. + + hbase.regionserver.global.memstore.size 0.4 Maximum size of all memstores in a region server before new diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemoryManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemoryManager.java index a66a29c..63bdac3 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemoryManager.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemoryManager.java @@ -18,6 +18,8 @@ */ package org.apache.hadoop.hbase.regionserver; +import static org.apache.hadoop.hbase.HConstants.HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD_DEFAULT; +import static org.apache.hadoop.hbase.HConstants.HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD_KEY; import static org.apache.hadoop.hbase.HConstants.HFILE_BLOCK_CACHE_SIZE_KEY; import java.lang.management.ManagementFactory; @@ -47,8 +49,6 @@ import com.google.common.annotations.VisibleForTesting; public class HeapMemoryManager { private static final Log LOG = LogFactory.getLog(HeapMemoryManager.class); private static final int CONVERT_TO_PERCENTAGE = 100; - private static final int CLUSTER_MINIMUM_MEMORY_THRESHOLD = - (int) (CONVERT_TO_PERCENTAGE * HConstants.HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD); public static final String BLOCK_CACHE_SIZE_MAX_RANGE_KEY = "hfile.block.cache.size.max.range"; public static final String BLOCK_CACHE_SIZE_MIN_RANGE_KEY = "hfile.block.cache.size.min.range"; @@ -62,6 +62,7 @@ public class HeapMemoryManager { public static final String HBASE_RS_HEAP_MEMORY_TUNER_CLASS = "hbase.regionserver.heapmemory.tuner.class"; + private float clusterMinimumMemoryThreshold; private float globalMemStorePercent; private float globalMemStorePercentMinRange; private float globalMemStorePercentMaxRange; @@ -112,6 +113,8 @@ public class HeapMemoryManager { blockCachePercent = conf.getFloat(HFILE_BLOCK_CACHE_SIZE_KEY, HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT); HeapMemorySizeUtil.checkForClusterFreeMemoryLimit(conf); + clusterMinimumMemoryThreshold = conf.getFloat(HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD_KEY, + HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD_DEFAULT); // Initialize max and min range for memstore heap space globalMemStorePercentMinRange = conf.getFloat(MEMSTORE_SIZE_MIN_RANGE_KEY, globalMemStorePercent); @@ -160,25 +163,27 @@ public class HeapMemoryManager { int gml = (int) (globalMemStorePercentMaxRange * CONVERT_TO_PERCENTAGE); this.l2BlockCachePercent = HeapMemorySizeUtil.getL2BlockCacheHeapPercent(conf); int bcul = (int) ((blockCachePercentMinRange + l2BlockCachePercent) * CONVERT_TO_PERCENTAGE); - if (CONVERT_TO_PERCENTAGE - (gml + bcul) < CLUSTER_MINIMUM_MEMORY_THRESHOLD) { + if (CONVERT_TO_PERCENTAGE - (gml + bcul) < clusterMinimumMemoryThreshold) { throw new RuntimeException("Current heap configuration for MemStore and BlockCache exceeds " + "the threshold required for successful cluster operation. " - + "The combined value cannot exceed 0.8. Please check the settings for " - + MEMSTORE_SIZE_MAX_RANGE_KEY + " and " + BLOCK_CACHE_SIZE_MIN_RANGE_KEY - + " in your configuration. " + MEMSTORE_SIZE_MAX_RANGE_KEY + " is " - + globalMemStorePercentMaxRange + " and " + BLOCK_CACHE_SIZE_MIN_RANGE_KEY + " is " - + blockCachePercentMinRange); + + "The combined value cannot exceed " + + String.format("%.1f", 1 - clusterMinimumMemoryThreshold) + + ". Please check the settings for " + MEMSTORE_SIZE_MAX_RANGE_KEY + " and " + + BLOCK_CACHE_SIZE_MIN_RANGE_KEY + " in your configuration. " + + MEMSTORE_SIZE_MAX_RANGE_KEY + " is " + globalMemStorePercentMaxRange + + " and " + BLOCK_CACHE_SIZE_MIN_RANGE_KEY + " is " + blockCachePercentMinRange); } gml = (int) (globalMemStorePercentMinRange * CONVERT_TO_PERCENTAGE); bcul = (int) ((blockCachePercentMaxRange + l2BlockCachePercent) * CONVERT_TO_PERCENTAGE); - if (CONVERT_TO_PERCENTAGE - (gml + bcul) < CLUSTER_MINIMUM_MEMORY_THRESHOLD) { + if (CONVERT_TO_PERCENTAGE - (gml + bcul) < clusterMinimumMemoryThreshold) { throw new RuntimeException("Current heap configuration for MemStore and BlockCache exceeds " + "the threshold required for successful cluster operation. " - + "The combined value cannot exceed 0.8. Please check the settings for " - + MEMSTORE_SIZE_MIN_RANGE_KEY + " and " + BLOCK_CACHE_SIZE_MAX_RANGE_KEY - + " in your configuration. " + MEMSTORE_SIZE_MIN_RANGE_KEY + " is " - + globalMemStorePercentMinRange + " and " + BLOCK_CACHE_SIZE_MAX_RANGE_KEY + " is " - + blockCachePercentMaxRange); + + "The combined value cannot exceed " + + String.format("%.1f", 1 - clusterMinimumMemoryThreshold) + + ". Please check the settings for " + MEMSTORE_SIZE_MIN_RANGE_KEY + " and " + + BLOCK_CACHE_SIZE_MAX_RANGE_KEY + " in your configuration. " + + MEMSTORE_SIZE_MIN_RANGE_KEY + " is " + globalMemStorePercentMinRange + " and " + + BLOCK_CACHE_SIZE_MAX_RANGE_KEY + " is " + blockCachePercentMaxRange); } return true; } @@ -303,10 +308,12 @@ public class HeapMemoryManager { } int gml = (int) (memstoreSize * CONVERT_TO_PERCENTAGE); int bcul = (int) ((blockCacheSize + l2BlockCachePercent) * CONVERT_TO_PERCENTAGE); - if (CONVERT_TO_PERCENTAGE - (gml + bcul) < CLUSTER_MINIMUM_MEMORY_THRESHOLD) { + if (CONVERT_TO_PERCENTAGE - (gml + bcul) < clusterMinimumMemoryThreshold) { LOG.info("Current heap configuration from HeapMemoryTuner exceeds " + "the threshold required for successful cluster operation. " - + "The combined value cannot exceed 0.8. " + HeapMemorySizeUtil.MEMSTORE_SIZE_KEY + + "The combined value cannot exceed " + + String.format("%.1f", 1 - clusterMinimumMemoryThreshold) + + " " + HeapMemorySizeUtil.MEMSTORE_SIZE_KEY + " is " + memstoreSize + " and " + HFILE_BLOCK_CACHE_SIZE_KEY + " is " + blockCacheSize); // TODO can adjust the value so as not exceed 80%. Is that correct? may be. -- 2.4.2