1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.client.backoff;
19
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22 import org.apache.hadoop.conf.Configuration;
23 import org.apache.hadoop.hbase.HConstants;
24 import org.apache.hadoop.hbase.ServerName;
25 import org.apache.hadoop.hbase.classification.InterfaceAudience;
26 import org.apache.hadoop.hbase.classification.InterfaceStability;
27
28 import com.google.common.base.Preconditions;
29
30
31
32
33
34 @InterfaceAudience.Public
35 @InterfaceStability.Unstable
36 public class ExponentialClientBackoffPolicy implements ClientBackoffPolicy {
37
38 private static final Log LOG = LogFactory.getLog(ExponentialClientBackoffPolicy.class);
39
40 private static final long ONE_MINUTE = 60 * 1000;
41 public static final long DEFAULT_MAX_BACKOFF = 5 * ONE_MINUTE;
42 public static final String MAX_BACKOFF_KEY = "hbase.client.exponential-backoff.max";
43 private long maxBackoff;
44 private float heapOccupancyLowWatermark;
45 private float heapOccupancyHighWatermark;
46
47 public ExponentialClientBackoffPolicy(Configuration conf) {
48 this.maxBackoff = conf.getLong(MAX_BACKOFF_KEY, DEFAULT_MAX_BACKOFF);
49 this.heapOccupancyLowWatermark = conf.getFloat(HConstants.HEAP_OCCUPANCY_LOW_WATERMARK_KEY,
50 HConstants.DEFAULT_HEAP_OCCUPANCY_LOW_WATERMARK);
51 this.heapOccupancyHighWatermark = conf.getFloat(HConstants.HEAP_OCCUPANCY_HIGH_WATERMARK_KEY,
52 HConstants.DEFAULT_HEAP_OCCUPANCY_HIGH_WATERMARK);
53 }
54
55 @Override
56 public long getBackoffTime(ServerName serverName, byte[] region, ServerStatistics stats) {
57
58 if (stats == null) {
59 return 0;
60 }
61
62 ServerStatistics.RegionStatistics regionStats = stats.getStatsForRegion(region);
63
64 if (regionStats == null) {
65 return 0;
66 }
67
68
69 double percent = regionStats.getMemstoreLoadPercent() / 100.0;
70
71
72 float heapOccupancy = regionStats.getHeapOccupancyPercent() / 100.0f;
73
74
75 float compactionPressure = regionStats.getCompactionPressure() / 100.0f;
76 if (heapOccupancy >= heapOccupancyLowWatermark) {
77
78
79 if (heapOccupancy > heapOccupancyHighWatermark) {
80 heapOccupancy = heapOccupancyHighWatermark;
81 }
82 percent = Math.max(percent,
83 scale(heapOccupancy, heapOccupancyLowWatermark, heapOccupancyHighWatermark,
84 0.1, 1.0));
85 }
86 percent = Math.max(percent, compactionPressure);
87
88
89 double multiplier = Math.pow(percent, 4.0);
90 if (multiplier > 1) {
91 multiplier = 1;
92 }
93 return (long) (multiplier * maxBackoff);
94 }
95
96
97 private static double scale(double valueIn, double baseMin, double baseMax, double limitMin,
98 double limitMax) {
99 Preconditions.checkArgument(baseMin <= baseMax, "Illegal source range [%s,%s]",
100 baseMin, baseMax);
101 Preconditions.checkArgument(limitMin <= limitMax, "Illegal target range [%s,%s]",
102 limitMin, limitMax);
103 Preconditions.checkArgument(valueIn >= baseMin && valueIn <= baseMax,
104 "Value %s must be within the range [%s,%s]", valueIn, baseMin, baseMax);
105 return ((limitMax - limitMin) * (valueIn - baseMin) / (baseMax - baseMin)) + limitMin;
106 }
107 }