HBASE-26921 Rewrite the counting cells part in TestMultiVersions (#4316)
[hbase.git] / hbase-server / src / main / java / org / apache / hadoop / hbase / regionserver / RegionServerAccounting.java
blobc406221f4f9f15ed97fb04a1b5c3c63eba0dda2d
1 /*
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 package org.apache.hadoop.hbase.regionserver;
21 import java.lang.management.MemoryType;
22 import java.util.concurrent.ConcurrentHashMap;
23 import java.util.concurrent.ConcurrentMap;
24 import java.util.concurrent.atomic.LongAdder;
26 import org.apache.hadoop.conf.Configuration;
27 import org.apache.yetus.audience.InterfaceAudience;
28 import org.apache.hadoop.hbase.io.util.MemorySizeUtil;
29 import org.apache.hadoop.hbase.util.Pair;
31 /**
32 * RegionServerAccounting keeps record of some basic real time information about
33 * the Region Server. Currently, it keeps record the global memstore size and global memstore
34 * on-heap and off-heap overhead. It also tracks the replay edits per region.
36 @InterfaceAudience.Private
37 public class RegionServerAccounting {
38 // memstore data size
39 private final LongAdder globalMemStoreDataSize = new LongAdder();
40 // memstore heap size.
41 private final LongAdder globalMemStoreHeapSize = new LongAdder();
42 // memstore off-heap size.
43 private final LongAdder globalMemStoreOffHeapSize = new LongAdder();
45 private long globalMemStoreLimit;
46 private final float globalMemStoreLimitLowMarkPercent;
47 private long globalMemStoreLimitLowMark;
48 private final MemoryType memType;
49 private long globalOnHeapMemstoreLimit;
50 private long globalOnHeapMemstoreLimitLowMark;
52 // encoded region name -> Pair -> read count as first, write count as second.
53 // when region close and target rs is the current server, we will put an entry,
54 // and will remove it when reigon open after recover them.
55 private ConcurrentMap<String, Pair<Long, Long>> retainedRegionRWRequestsCnt;
57 public RegionServerAccounting(Configuration conf) {
58 Pair<Long, MemoryType> globalMemstoreSizePair = MemorySizeUtil.getGlobalMemStoreSize(conf);
59 this.globalMemStoreLimit = globalMemstoreSizePair.getFirst();
60 this.memType = globalMemstoreSizePair.getSecond();
61 this.globalMemStoreLimitLowMarkPercent =
62 MemorySizeUtil.getGlobalMemStoreHeapLowerMark(conf, this.memType == MemoryType.HEAP);
63 // When off heap memstore in use we configure the global off heap space for memstore as bytes
64 // not as % of max memory size. In such case, the lower water mark should be specified using the
65 // key "hbase.regionserver.global.memstore.size.lower.limit" which says % of the global upper
66 // bound and defaults to 95%. In on heap case also specifying this way is ideal. But in the past
67 // we used to take lower bound also as the % of xmx (38% as default). For backward compatibility
68 // for this deprecated config,we will fall back to read that config when new one is missing.
69 // Only for on heap case, do this fallback mechanism. For off heap it makes no sense.
70 // TODO When to get rid of the deprecated config? ie
71 // "hbase.regionserver.global.memstore.lowerLimit". Can get rid of this boolean passing then.
72 this.globalMemStoreLimitLowMark =
73 (long) (this.globalMemStoreLimit * this.globalMemStoreLimitLowMarkPercent);
74 this.globalOnHeapMemstoreLimit = MemorySizeUtil.getOnheapGlobalMemStoreSize(conf);
75 this.globalOnHeapMemstoreLimitLowMark =
76 (long) (this.globalOnHeapMemstoreLimit * this.globalMemStoreLimitLowMarkPercent);
77 this.retainedRegionRWRequestsCnt = new ConcurrentHashMap<>();
80 long getGlobalMemStoreLimit() {
81 return this.globalMemStoreLimit;
84 long getGlobalOnHeapMemStoreLimit() {
85 return this.globalOnHeapMemstoreLimit;
88 // Called by the tuners.
89 void setGlobalMemStoreLimits(long newGlobalMemstoreLimit) {
90 if (this.memType == MemoryType.HEAP) {
91 this.globalMemStoreLimit = newGlobalMemstoreLimit;
92 this.globalMemStoreLimitLowMark =
93 (long) (this.globalMemStoreLimit * this.globalMemStoreLimitLowMarkPercent);
94 } else {
95 this.globalOnHeapMemstoreLimit = newGlobalMemstoreLimit;
96 this.globalOnHeapMemstoreLimitLowMark =
97 (long) (this.globalOnHeapMemstoreLimit * this.globalMemStoreLimitLowMarkPercent);
101 boolean isOffheap() {
102 return this.memType == MemoryType.NON_HEAP;
105 long getGlobalMemStoreLimitLowMark() {
106 return this.globalMemStoreLimitLowMark;
109 float getGlobalMemStoreLimitLowMarkPercent() {
110 return this.globalMemStoreLimitLowMarkPercent;
114 * @return the global Memstore data size in the RegionServer
116 public long getGlobalMemStoreDataSize() {
117 return globalMemStoreDataSize.sum();
121 * @return the global memstore heap size in the RegionServer
123 public long getGlobalMemStoreHeapSize() {
124 return this.globalMemStoreHeapSize.sum();
128 * @return the global memstore heap size in the RegionServer
130 public long getGlobalMemStoreOffHeapSize() {
131 return this.globalMemStoreOffHeapSize.sum();
135 * @return the retained metrics of region's read and write requests count
137 protected ConcurrentMap<String, Pair<Long, Long>> getRetainedRegionRWRequestsCnt() {
138 return this.retainedRegionRWRequestsCnt;
141 void incGlobalMemStoreSize(MemStoreSize mss) {
142 incGlobalMemStoreSize(mss.getDataSize(), mss.getHeapSize(), mss.getOffHeapSize());
145 public void incGlobalMemStoreSize(long dataSizeDelta, long heapSizeDelta, long offHeapSizeDelta) {
146 globalMemStoreDataSize.add(dataSizeDelta);
147 globalMemStoreHeapSize.add(heapSizeDelta);
148 globalMemStoreOffHeapSize.add(offHeapSizeDelta);
151 public void decGlobalMemStoreSize(long dataSizeDelta, long heapSizeDelta, long offHeapSizeDelta) {
152 globalMemStoreDataSize.add(-dataSizeDelta);
153 globalMemStoreHeapSize.add(-heapSizeDelta);
154 globalMemStoreOffHeapSize.add(-offHeapSizeDelta);
158 * Return true if we are above the memstore high water mark
159 * @return the flushtype
161 public FlushType isAboveHighWaterMark() {
162 // for onheap memstore we check if the global memstore size and the
163 // global heap overhead is greater than the global memstore limit
164 if (memType == MemoryType.HEAP) {
165 if (getGlobalMemStoreHeapSize() >= globalMemStoreLimit) {
166 return FlushType.ABOVE_ONHEAP_HIGHER_MARK;
168 } else {
169 // If the configured memstore is offheap, check for two things
170 // 1) If the global memstore off-heap size is greater than the configured
171 // 'hbase.regionserver.offheap.global.memstore.size'
172 // 2) If the global memstore heap size is greater than the configured onheap
173 // global memstore limit 'hbase.regionserver.global.memstore.size'.
174 // We do this to avoid OOME incase of scenarios where the heap is occupied with
175 // lot of onheap references to the cells in memstore
176 if (getGlobalMemStoreOffHeapSize() >= globalMemStoreLimit) {
177 // Indicates that global memstore size is above the configured
178 // 'hbase.regionserver.offheap.global.memstore.size'
179 return FlushType.ABOVE_OFFHEAP_HIGHER_MARK;
180 } else if (getGlobalMemStoreHeapSize() >= this.globalOnHeapMemstoreLimit) {
181 // Indicates that the offheap memstore's heap overhead is greater than the
182 // configured 'hbase.regionserver.global.memstore.size'.
183 return FlushType.ABOVE_ONHEAP_HIGHER_MARK;
186 return FlushType.NORMAL;
190 * Return true if we're above the low watermark
192 public FlushType isAboveLowWaterMark() {
193 // for onheap memstore we check if the global memstore size and the
194 // global heap overhead is greater than the global memstore lower mark limit
195 if (memType == MemoryType.HEAP) {
196 if (getGlobalMemStoreHeapSize() >= globalMemStoreLimitLowMark) {
197 return FlushType.ABOVE_ONHEAP_LOWER_MARK;
199 } else {
200 if (getGlobalMemStoreOffHeapSize() >= globalMemStoreLimitLowMark) {
201 // Indicates that the offheap memstore's size is greater than the global memstore
202 // lower limit
203 return FlushType.ABOVE_OFFHEAP_LOWER_MARK;
204 } else if (getGlobalMemStoreHeapSize() >= globalOnHeapMemstoreLimitLowMark) {
205 // Indicates that the offheap memstore's heap overhead is greater than the global memstore
206 // onheap lower limit
207 return FlushType.ABOVE_ONHEAP_LOWER_MARK;
210 return FlushType.NORMAL;
214 * @return the flush pressure of all stores on this regionserver. The value should be greater than
215 * or equal to 0.0, and any value greater than 1.0 means we enter the emergency state that
216 * global memstore size already exceeds lower limit.
218 public double getFlushPressure() {
219 if (memType == MemoryType.HEAP) {
220 return (getGlobalMemStoreHeapSize()) * 1.0 / globalMemStoreLimitLowMark;
221 } else {
222 return Math.max(getGlobalMemStoreOffHeapSize() * 1.0 / globalMemStoreLimitLowMark,
223 getGlobalMemStoreHeapSize() * 1.0 / globalOnHeapMemstoreLimitLowMark);