| /** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.hadoop.hbase.regionserver; |
| |
| import org.apache.yetus.audience.InterfaceAudience; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| import org.apache.hadoop.conf.Configuration; |
| import org.apache.hadoop.hbase.regionserver.compactions.CompactionConfiguration; |
| |
| /** |
| * Configuration class for stripe store and compactions. |
| * See {@link StripeStoreFileManager} for general documentation. |
| * See getters for the description of each setting. |
| */ |
| @InterfaceAudience.Private |
| public class StripeStoreConfig { |
| private static final Logger LOG = LoggerFactory.getLogger(StripeStoreConfig.class); |
| |
| /** The maximum number of files to compact within a stripe; same as for regular compaction. */ |
| public static final String MAX_FILES_KEY = "hbase.store.stripe.compaction.maxFiles"; |
| /** The minimum number of files to compact within a stripe; same as for regular compaction. */ |
| public static final String MIN_FILES_KEY = "hbase.store.stripe.compaction.minFiles"; |
| |
| /** The minimum number of files to compact when compacting L0; same as minFiles for regular |
| * compaction. Given that L0 causes unnecessary overwriting of the data, should be higher than |
| * regular minFiles. */ |
| public static final String MIN_FILES_L0_KEY = "hbase.store.stripe.compaction.minFilesL0"; |
| |
| /** The size the stripe should achieve to be considered for splitting into multiple stripes. |
| Stripe will be split when it can be fully compacted, and it is above this size. */ |
| public static final String SIZE_TO_SPLIT_KEY = "hbase.store.stripe.sizeToSplit"; |
| /** The target count of new stripes to produce when splitting a stripe. A floating point |
| number, default is 2. Values less than 1 will be converted to 1/x. Non-whole numbers will |
| produce unbalanced splits, which may be good for some cases. In this case the "smaller" of |
| the new stripes will always be the rightmost one. If the stripe is bigger than sizeToSplit |
| when splitting, this will be adjusted by a whole increment. */ |
| public static final String SPLIT_PARTS_KEY = "hbase.store.stripe.splitPartCount"; |
| /** The initial stripe count to create. If the row distribution is roughly the same over time, |
| it's good to set this to a count of stripes that is expected to be achieved in most regions, |
| to get this count from the outset and prevent unnecessary splitting. */ |
| public static final String INITIAL_STRIPE_COUNT_KEY = "hbase.store.stripe.initialStripeCount"; |
| |
| /** Whether to flush memstore to L0 files, or directly to stripes. */ |
| public static final String FLUSH_TO_L0_KEY = "hbase.store.stripe.compaction.flushToL0"; |
| |
| /** When splitting region, the maximum size imbalance to allow in an attempt to split at a |
| stripe boundary, so that no files go to both regions. Most users won't need to change that. */ |
| public static final String MAX_REGION_SPLIT_IMBALANCE_KEY = |
| "hbase.store.stripe.region.split.max.imbalance"; |
| |
| |
| private final float maxRegionSplitImbalance; |
| private final int level0CompactMinFiles; |
| private final int stripeCompactMinFiles; |
| private final int stripeCompactMaxFiles; |
| |
| private final int initialCount; |
| private final long sizeToSplitAt; |
| private final float splitPartCount; |
| private final boolean flushIntoL0; |
| private final long splitPartSize; // derived from sizeToSplitAt and splitPartCount |
| |
| private static final double EPSILON = 0.001; // good enough for this, not a real epsilon. |
| public StripeStoreConfig(Configuration config, StoreConfigInformation sci) { |
| this.level0CompactMinFiles = config.getInt(MIN_FILES_L0_KEY, 4); |
| this.flushIntoL0 = config.getBoolean(FLUSH_TO_L0_KEY, false); |
| int minMinFiles = flushIntoL0 ? 3 : 4; // make sure not to compact tiny files too often. |
| int minFiles = config.getInt(CompactionConfiguration.HBASE_HSTORE_COMPACTION_MIN_KEY, -1); |
| this.stripeCompactMinFiles = config.getInt(MIN_FILES_KEY, Math.max(minMinFiles, minFiles)); |
| this.stripeCompactMaxFiles = config.getInt(MAX_FILES_KEY, |
| config.getInt(CompactionConfiguration.HBASE_HSTORE_COMPACTION_MAX_KEY, 10)); |
| this.maxRegionSplitImbalance = getFloat(config, MAX_REGION_SPLIT_IMBALANCE_KEY, 1.5f, true); |
| |
| float splitPartCount = getFloat(config, SPLIT_PARTS_KEY, 2f, true); |
| if (Math.abs(splitPartCount - 1.0) < EPSILON) { |
| LOG.error("Split part count cannot be 1 (" + splitPartCount + "), using the default"); |
| splitPartCount = 2f; |
| } |
| this.splitPartCount = splitPartCount; |
| // Arbitrary default split size - 4 times the size of one L0 compaction. |
| // If we flush into L0 there's no split compaction, but for default value it is ok. |
| double flushSize = sci.getMemStoreFlushSize(); |
| if (flushSize == 0) { |
| flushSize = 128 * 1024 * 1024; |
| } |
| long defaultSplitSize = (long)(flushSize * getLevel0MinFiles() * 4 * splitPartCount); |
| this.sizeToSplitAt = config.getLong(SIZE_TO_SPLIT_KEY, defaultSplitSize); |
| int initialCount = config.getInt(INITIAL_STRIPE_COUNT_KEY, 1); |
| if (initialCount == 0) { |
| LOG.error("Initial stripe count is 0, using the default"); |
| initialCount = 1; |
| } |
| this.initialCount = initialCount; |
| this.splitPartSize = (long)(this.sizeToSplitAt / this.splitPartCount); |
| } |
| |
| private static float getFloat( |
| Configuration config, String key, float defaultValue, boolean moreThanOne) { |
| float value = config.getFloat(key, defaultValue); |
| if (value < EPSILON) { |
| LOG.warn(String.format( |
| "%s is set to 0 or negative; using default value of %f", key, defaultValue)); |
| value = defaultValue; |
| } else if ((value > 1f) != moreThanOne) { |
| value = 1f / value; |
| } |
| return value; |
| } |
| |
| public float getMaxSplitImbalance() { |
| return this.maxRegionSplitImbalance; |
| } |
| |
| public int getLevel0MinFiles() { |
| return level0CompactMinFiles; |
| } |
| |
| public int getStripeCompactMinFiles() { |
| return stripeCompactMinFiles; |
| } |
| |
| public int getStripeCompactMaxFiles() { |
| return stripeCompactMaxFiles; |
| } |
| |
| public boolean isUsingL0Flush() { |
| return flushIntoL0; |
| } |
| |
| public long getSplitSize() { |
| return sizeToSplitAt; |
| } |
| |
| public int getInitialCount() { |
| return initialCount; |
| } |
| |
| public float getSplitCount() { |
| return splitPartCount; |
| } |
| |
| /** |
| * @return the desired size of the target stripe when splitting, in bytes. |
| * Derived from {@link #getSplitSize()} and {@link #getSplitCount()}. |
| */ |
| public long getSplitPartSize() { |
| return splitPartSize; |
| } |
| } |