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.balancer;
20
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.hadoop.classification.InterfaceAudience;
31 import org.apache.hadoop.conf.Configuration;
32 import org.apache.hadoop.hbase.HRegionInfo;
33 import org.apache.hadoop.hbase.ServerLoad;
34 import org.apache.hadoop.hbase.ServerName;
35 import org.apache.hadoop.hbase.master.LoadBalancer;
36 import org.apache.hadoop.hbase.master.RackManager;
37 import org.apache.hadoop.hbase.master.RegionPlan;
38 import org.apache.hadoop.hbase.master.balancer.FavoredNodes.Position;
39 import org.apache.hadoop.hbase.util.Pair;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 @InterfaceAudience.Private
55 public class FavoredNodeLoadBalancer extends BaseLoadBalancer {
56 private static final Log LOG = LogFactory.getLog(FavoredNodeLoadBalancer.class);
57
58 private FavoredNodes globalFavoredNodesAssignmentPlan;
59 private RackManager rackManager;
60
61 @Override
62 public void setConf(Configuration conf) {
63 globalFavoredNodesAssignmentPlan = new FavoredNodes();
64 this.rackManager = new RackManager(conf);
65 }
66
67 @Override
68 public List<RegionPlan> balanceCluster(Map<ServerName, List<HRegionInfo>> clusterState) {
69
70
71
72
73
74 throw new UnsupportedOperationException("Not implemented yet");
75 }
76
77 @Override
78 public Map<ServerName, List<HRegionInfo>> roundRobinAssignment(List<HRegionInfo> regions,
79 List<ServerName> servers) {
80 Map<ServerName, List<HRegionInfo>> assignmentMap;
81 try {
82 FavoredNodeAssignmentHelper assignmentHelper =
83 new FavoredNodeAssignmentHelper(servers, rackManager);
84 assignmentHelper.initialize();
85 if (!assignmentHelper.canPlaceFavoredNodes()) {
86 return super.roundRobinAssignment(regions, servers);
87 }
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 Pair<Map<ServerName,List<HRegionInfo>>, List<HRegionInfo>> segregatedRegions =
105 segregateRegionsAndAssignRegionsWithFavoredNodes(regions, servers);
106 Map<ServerName,List<HRegionInfo>> regionsWithFavoredNodesMap = segregatedRegions.getFirst();
107 List<HRegionInfo> regionsWithNoFavoredNodes = segregatedRegions.getSecond();
108 assignmentMap = new HashMap<ServerName, List<HRegionInfo>>();
109 roundRobinAssignmentImpl(assignmentHelper, assignmentMap, regionsWithNoFavoredNodes,
110 servers);
111
112 assignmentMap.putAll(regionsWithFavoredNodesMap);
113 } catch (Exception ex) {
114 LOG.warn("Encountered exception while doing favored-nodes assignment " + ex +
115 " Falling back to regular assignment");
116 assignmentMap = super.roundRobinAssignment(regions, servers);
117 }
118 return assignmentMap;
119 }
120
121 @Override
122 public ServerName randomAssignment(HRegionInfo regionInfo, List<ServerName> servers) {
123 try {
124 FavoredNodeAssignmentHelper assignmentHelper =
125 new FavoredNodeAssignmentHelper(servers, rackManager);
126 assignmentHelper.initialize();
127 ServerName primary = super.randomAssignment(regionInfo, servers);
128 if (!assignmentHelper.canPlaceFavoredNodes()) {
129 return primary;
130 }
131 List<ServerName> favoredNodes = globalFavoredNodesAssignmentPlan.getFavoredNodes(regionInfo);
132
133
134
135 if (favoredNodes != null) {
136 for (ServerName s : favoredNodes) {
137 ServerName serverWithLegitStartCode = availableServersContains(servers, s);
138 if (serverWithLegitStartCode != null) {
139 return serverWithLegitStartCode;
140 }
141 }
142 }
143 List<HRegionInfo> regions = new ArrayList<HRegionInfo>(1);
144 regions.add(regionInfo);
145 Map<HRegionInfo, ServerName> primaryRSMap = new HashMap<HRegionInfo, ServerName>(1);
146 primaryRSMap.put(regionInfo, primary);
147 assignSecondaryAndTertiaryNodesForRegion(assignmentHelper, regions, primaryRSMap);
148 return primary;
149 } catch (Exception ex) {
150 LOG.warn("Encountered exception while doing favored-nodes (random)assignment " + ex +
151 " Falling back to regular assignment");
152 return super.randomAssignment(regionInfo, servers);
153 }
154 }
155
156 private Pair<Map<ServerName, List<HRegionInfo>>, List<HRegionInfo>>
157 segregateRegionsAndAssignRegionsWithFavoredNodes(List<HRegionInfo> regions,
158 List<ServerName> availableServers) {
159 Map<ServerName, List<HRegionInfo>> assignmentMapForFavoredNodes =
160 new HashMap<ServerName, List<HRegionInfo>>(regions.size() / 2);
161 List<HRegionInfo> regionsWithNoFavoredNodes = new ArrayList<HRegionInfo>(regions.size()/2);
162 for (HRegionInfo region : regions) {
163 List<ServerName> favoredNodes = globalFavoredNodesAssignmentPlan.getFavoredNodes(region);
164 ServerName primaryHost = null;
165 ServerName secondaryHost = null;
166 ServerName tertiaryHost = null;
167 if (favoredNodes != null) {
168 for (ServerName s : favoredNodes) {
169 ServerName serverWithLegitStartCode = availableServersContains(availableServers, s);
170 if (serverWithLegitStartCode != null) {
171 FavoredNodes.Position position =
172 FavoredNodes.getFavoredServerPosition(favoredNodes, s);
173 if (Position.PRIMARY.equals(position)) {
174 primaryHost = serverWithLegitStartCode;
175 } else if (Position.SECONDARY.equals(position)) {
176 secondaryHost = serverWithLegitStartCode;
177 } else if (Position.TERTIARY.equals(position)) {
178 tertiaryHost = serverWithLegitStartCode;
179 }
180 }
181 }
182 assignRegionToAvailableFavoredNode(assignmentMapForFavoredNodes, region,
183 primaryHost, secondaryHost, tertiaryHost);
184 }
185 if (primaryHost == null && secondaryHost == null && tertiaryHost == null) {
186
187 regionsWithNoFavoredNodes.add(region);
188 }
189 }
190 return new Pair<Map<ServerName, List<HRegionInfo>>, List<HRegionInfo>>(
191 assignmentMapForFavoredNodes, regionsWithNoFavoredNodes);
192 }
193
194
195
196
197 private ServerName availableServersContains(List<ServerName> servers, ServerName favoredNode) {
198 for (ServerName server : servers) {
199 if (ServerName.isSameHostnameAndPort(favoredNode, server)) {
200 return server;
201 }
202 }
203 return null;
204 }
205
206 private void assignRegionToAvailableFavoredNode(Map<ServerName,
207 List<HRegionInfo>> assignmentMapForFavoredNodes, HRegionInfo region, ServerName primaryHost,
208 ServerName secondaryHost, ServerName tertiaryHost) {
209 if (primaryHost != null) {
210 addRegionToMap(assignmentMapForFavoredNodes, region, primaryHost);
211 } else if (secondaryHost != null && tertiaryHost != null) {
212
213
214 ServerName s;
215 ServerLoad tertiaryLoad = super.services.getServerManager().getLoad(tertiaryHost);
216 ServerLoad secondaryLoad = super.services.getServerManager().getLoad(secondaryHost);
217 if (secondaryLoad.getLoad() < tertiaryLoad.getLoad()) {
218 s = secondaryHost;
219 } else {
220 s = tertiaryHost;
221 }
222 addRegionToMap(assignmentMapForFavoredNodes, region, s);
223 } else if (secondaryHost != null) {
224 addRegionToMap(assignmentMapForFavoredNodes, region, secondaryHost);
225 } else if (tertiaryHost != null) {
226 addRegionToMap(assignmentMapForFavoredNodes, region, tertiaryHost);
227 }
228 }
229
230 private void addRegionToMap(Map<ServerName, List<HRegionInfo>> assignmentMapForFavoredNodes,
231 HRegionInfo region, ServerName host) {
232 List<HRegionInfo> regionsOnServer = null;
233 if ((regionsOnServer = assignmentMapForFavoredNodes.get(host)) == null) {
234 regionsOnServer = new ArrayList<HRegionInfo>();
235 assignmentMapForFavoredNodes.put(host, regionsOnServer);
236 }
237 regionsOnServer.add(region);
238 }
239
240 public List<ServerName> getFavoredNodes(HRegionInfo regionInfo) {
241 return this.globalFavoredNodesAssignmentPlan.getFavoredNodes(regionInfo);
242 }
243
244 private void roundRobinAssignmentImpl(FavoredNodeAssignmentHelper assignmentHelper,
245 Map<ServerName, List<HRegionInfo>> assignmentMap,
246 List<HRegionInfo> regions, List<ServerName> servers) throws IOException {
247 Map<HRegionInfo, ServerName> primaryRSMap = new HashMap<HRegionInfo, ServerName>();
248
249 assignmentHelper.placePrimaryRSAsRoundRobin(assignmentMap, primaryRSMap, regions);
250 assignSecondaryAndTertiaryNodesForRegion(assignmentHelper, regions, primaryRSMap);
251 }
252
253 private void assignSecondaryAndTertiaryNodesForRegion(
254 FavoredNodeAssignmentHelper assignmentHelper,
255 List<HRegionInfo> regions, Map<HRegionInfo, ServerName> primaryRSMap) {
256
257 Map<HRegionInfo, ServerName[]> secondaryAndTertiaryRSMap =
258 assignmentHelper.placeSecondaryAndTertiaryRS(primaryRSMap);
259
260 for (HRegionInfo region : regions) {
261
262
263 List<ServerName> favoredNodesForRegion = new ArrayList<ServerName>(3);
264 ServerName sn = primaryRSMap.get(region);
265 favoredNodesForRegion.add(new ServerName(sn.getHostname(), sn.getPort(),
266 ServerName.NON_STARTCODE));
267 ServerName[] secondaryAndTertiaryNodes = secondaryAndTertiaryRSMap.get(region);
268 if (secondaryAndTertiaryNodes != null) {
269 favoredNodesForRegion.add(new ServerName(secondaryAndTertiaryNodes[0].getHostname(),
270 secondaryAndTertiaryNodes[0].getPort(), ServerName.NON_STARTCODE));
271 favoredNodesForRegion.add(new ServerName(secondaryAndTertiaryNodes[1].getHostname(),
272 secondaryAndTertiaryNodes[1].getPort(), ServerName.NON_STARTCODE));
273 }
274 globalFavoredNodesAssignmentPlan.updateFavoredNodesMap(region, favoredNodesForRegion);
275 }
276 }
277
278 void noteFavoredNodes(final Map<HRegionInfo, ServerName[]> favoredNodesMap) {
279 for (Map.Entry<HRegionInfo, ServerName[]> entry : favoredNodesMap.entrySet()) {
280
281 globalFavoredNodesAssignmentPlan.updateFavoredNodesMap(entry.getKey(),
282 Arrays.asList(entry.getValue()));
283 }
284 }
285 }