1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.master.normalizer;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.hadoop.hbase.HBaseIOException;
24 import org.apache.hadoop.hbase.HRegionInfo;
25 import org.apache.hadoop.hbase.RegionLoad;
26 import org.apache.hadoop.hbase.ServerName;
27 import org.apache.hadoop.hbase.TableName;
28 import org.apache.hadoop.hbase.classification.InterfaceAudience;
29 import org.apache.hadoop.hbase.master.MasterServices;
30 import org.apache.hadoop.hbase.master.normalizer.NormalizationPlan;
31
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.Comparator;
35 import java.util.List;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 @InterfaceAudience.Private
57 public class SimpleRegionNormalizer implements RegionNormalizer {
58
59 private static final Log LOG = LogFactory.getLog(SimpleRegionNormalizer.class);
60 private static final int MIN_REGION_COUNT = 3;
61 private MasterServices masterServices;
62
63
64
65
66
67 @Override
68 public void setMasterServices(MasterServices masterServices) {
69 this.masterServices = masterServices;
70 }
71
72
73 private Comparator<NormalizationPlan> planComparator =
74 new Comparator<NormalizationPlan>() {
75 @Override
76 public int compare(NormalizationPlan plan, NormalizationPlan plan2) {
77 if (plan instanceof SplitNormalizationPlan) {
78 return -1;
79 }
80 if (plan2 instanceof SplitNormalizationPlan) {
81 return 1;
82 }
83 return 0;
84 }
85 };
86
87
88
89
90
91
92
93
94 @Override
95 public List<NormalizationPlan> computePlanForTable(TableName table) throws HBaseIOException {
96 if (table == null || table.isSystemTable()) {
97 LOG.debug("Normalization of system table " + table + " isn't allowed");
98 return null;
99 }
100
101 List<NormalizationPlan> plans = new ArrayList<NormalizationPlan>();
102 List<HRegionInfo> tableRegions = masterServices.getAssignmentManager().getRegionStates().
103 getRegionsOfTable(table);
104
105
106 if (tableRegions == null || tableRegions.size() < MIN_REGION_COUNT) {
107 int nrRegions = tableRegions == null ? 0 : tableRegions.size();
108 LOG.debug("Table " + table + " has " + nrRegions + " regions, required min number"
109 + " of regions for normalizer to run is " + MIN_REGION_COUNT + ", not running normalizer");
110 return null;
111 }
112
113 LOG.debug("Computing normalization plan for table: " + table +
114 ", number of regions: " + tableRegions.size());
115
116 long totalSizeMb = 0;
117 int acutalRegionCnt = 0;
118
119 for (int i = 0; i < tableRegions.size(); i++) {
120 HRegionInfo hri = tableRegions.get(i);
121 long regionSize = getRegionSize(hri);
122 if (regionSize > 0) {
123 acutalRegionCnt++;
124 totalSizeMb += regionSize;
125 }
126 }
127
128 double avgRegionSize = acutalRegionCnt == 0 ? 0 : totalSizeMb / (double) acutalRegionCnt;
129
130 LOG.debug("Table " + table + ", total aggregated regions size: " + totalSizeMb);
131 LOG.debug("Table " + table + ", average region size: " + avgRegionSize);
132
133 int candidateIdx = 0;
134 while (candidateIdx < tableRegions.size()) {
135 HRegionInfo hri = tableRegions.get(candidateIdx);
136 long regionSize = getRegionSize(hri);
137
138
139 if (regionSize > 2 * avgRegionSize) {
140 LOG.info("Table " + table + ", large region " + hri.getRegionNameAsString() + " has size "
141 + regionSize + ", more than twice avg size, splitting");
142 plans.add(new SplitNormalizationPlan(hri, null));
143 } else {
144 if (candidateIdx == tableRegions.size()-1) {
145 break;
146 }
147 HRegionInfo hri2 = tableRegions.get(candidateIdx+1);
148 long regionSize2 = getRegionSize(hri2);
149 if (regionSize >= 0 && regionSize2 >= 0 && regionSize + regionSize2 < avgRegionSize) {
150 LOG.info("Table " + table + ", small region size: " + regionSize
151 + " plus its neighbor size: " + regionSize2
152 + ", less than the avg size " + avgRegionSize + ", merging them");
153 plans.add(new MergeNormalizationPlan(hri, hri2));
154 candidateIdx++;
155 }
156 }
157 candidateIdx++;
158 }
159 if (plans.isEmpty()) {
160 LOG.debug("No normalization needed, regions look good for table: " + table);
161 return null;
162 }
163 Collections.sort(plans, planComparator);
164 return plans;
165 }
166
167 private long getRegionSize(HRegionInfo hri) {
168 ServerName sn = masterServices.getAssignmentManager().getRegionStates().
169 getRegionServerOfRegion(hri);
170 RegionLoad regionLoad = masterServices.getServerManager().getLoad(sn).
171 getRegionsLoad().get(hri.getRegionName());
172 if (regionLoad == null) {
173 LOG.debug(hri.getRegionNameAsString() + " was not found in RegionsLoad");
174 return -1;
175 }
176 return regionLoad.getStorefileSizeMB();
177 }
178 }