001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.master;
019
020import edu.umd.cs.findbugs.annotations.NonNull;
021import java.io.IOException;
022import java.time.Duration;
023import java.util.List;
024import java.util.Map;
025import org.apache.hadoop.conf.Configuration;
026import org.apache.hadoop.hbase.ClusterMetrics;
027import org.apache.hadoop.hbase.ServerName;
028import org.apache.hadoop.hbase.Stoppable;
029import org.apache.hadoop.hbase.TableName;
030import org.apache.hadoop.hbase.client.RegionInfo;
031import org.apache.hadoop.hbase.conf.ConfigurationObserver;
032import org.apache.hadoop.hbase.master.balancer.ClusterInfoProvider;
033import org.apache.yetus.audience.InterfaceAudience;
034
035/**
036 * Makes decisions about the placement and movement of Regions across RegionServers.
037 * <p/>
038 * Cluster-wide load balancing will occur only when there are no regions in transition and according
039 * to a fixed period of a time using {@link #balanceCluster(Map)}.
040 * <p/>
041 * On cluster startup, bulk assignment can be used to determine locations for all Regions in a
042 * cluster.
043 * <p/>
044 * This class produces plans for the {@code AssignmentManager} to execute.
045 * <p/>
046 * About locking:
047 * <ul>
048 * <li>We will first call {@link #setClusterInfoProvider(ClusterInfoProvider)} and then
049 * {@link #initialize()} to initialize the balancer, and before calling {@link #initialize()}, we
050 * will never call any methods of this balancer. So these two methods do not need to be
051 * synchronized.</li>
052 * <li>The {@link #balanceCluster(Map)} method will use the {@link ClusterMetrics} which is set by
053 * {@link #updateClusterMetrics(ClusterMetrics)}, and also lots of configurations, which could be
054 * changed by {@link #onConfigurationChange(Configuration)}, so the easier way is to make these
055 * three methods synchronized. And since there will be only one balancing thread, this will not
056 * impact performance too much.</li>
057 * <li>The {@link #roundRobinAssignment(List, List)}, {@link #retainAssignment(Map, List)} and
058 * {@link #randomAssignment(RegionInfo, List)} could be called from multiple threads concurrently,
059 * so these three methods should not be synchronized, the implementation classes need to make sure
060 * that they are thread safe.</li>
061 * </ul>
062 */
063@InterfaceAudience.Private
064public interface LoadBalancer extends Stoppable, ConfigurationObserver {
065
066  // Used to signal to the caller that the region(s) cannot be assigned
067  // We deliberately use 'localhost' so the operation will fail fast
068  ServerName BOGUS_SERVER_NAME = ServerName.valueOf("localhost,1,1");
069
070  /**
071   * Config for pluggable load balancers.
072   * @deprecated since 3.0.0, will be removed in 4.0.0. In the new implementation, as the base load
073   *             balancer will always be the rs group based one, you should just use
074   *             {@link org.apache.hadoop.hbase.HConstants#HBASE_MASTER_LOADBALANCER_CLASS} to
075   *             config the per group load balancer.
076   */
077  @Deprecated
078  String HBASE_RSGROUP_LOADBALANCER_CLASS = "hbase.rsgroup.grouploadbalancer.class";
079
080  /**
081   * Configuration to determine the time to sleep when throttling (if throttling is implemented by
082   * the underlying implementation).
083   */
084  String MOVE_THROTTLING = "hbase.master.balancer.move.throttlingMillis";
085
086  /**
087   * The default value, in milliseconds, for the hbase.master.balancer.move.throttlingMillis if
088   * throttling is implemented.
089   */
090  Duration MOVE_THROTTLING_DEFAULT = Duration.ofMillis(60 * 1000);
091
092  /**
093   * Set the current cluster status. This allows a LoadBalancer to map host name to a server
094   */
095  void updateClusterMetrics(ClusterMetrics metrics);
096
097  /**
098   * Set the cluster info provider. Usually it is just a wrapper of master.
099   */
100  void setClusterInfoProvider(ClusterInfoProvider provider);
101
102  /**
103   * Perform the major balance operation for cluster.
104   * @param loadOfAllTable region load of servers for all table
105   * @return a list of regions to be moved, including source and destination, or null if cluster is
106   *         already balanced
107   */
108  List<RegionPlan> balanceCluster(Map<TableName, Map<ServerName, List<RegionInfo>>> loadOfAllTable)
109    throws IOException;
110
111  /**
112   * Perform a Round Robin assignment of regions.
113   * @return Map of servername to regioninfos
114   */
115  @NonNull
116  Map<ServerName, List<RegionInfo>> roundRobinAssignment(List<RegionInfo> regions,
117    List<ServerName> servers) throws IOException;
118
119  /**
120   * Assign regions to the previously hosting region server
121   * @return List of plans
122   */
123  @NonNull
124  Map<ServerName, List<RegionInfo>> retainAssignment(Map<RegionInfo, ServerName> regions,
125    List<ServerName> servers) throws IOException;
126
127  /**
128   * Get a random region server from the list
129   * @param regionInfo Region for which this selection is being done.
130   */
131  ServerName randomAssignment(RegionInfo regionInfo, List<ServerName> servers) throws IOException;
132
133  /**
134   * Initialize the load balancer. Must be called after setters.
135   */
136  void initialize() throws IOException;
137
138  /**
139   * Marks the region as online at balancer.
140   */
141  void regionOnline(RegionInfo regionInfo, ServerName sn);
142
143  /**
144   * Marks the region as offline at balancer.
145   */
146  void regionOffline(RegionInfo regionInfo);
147
148  /**
149   * Notification that config has changed
150   */
151  @Override
152  void onConfigurationChange(Configuration conf);
153
154  /**
155   * If balancer needs to do initialization after Master has started up, lets do that here.
156   */
157  void postMasterStartupInitialize();
158
159  /* Updates balancer status tag reported to JMX */
160  void updateBalancerStatus(boolean status);
161
162  /**
163   * In some scenarios, Balancer needs to update internal status or information according to the
164   * current tables load
165   * @param loadOfAllTable region load of servers for all table
166   */
167  default void
168    updateBalancerLoadInfo(Map<TableName, Map<ServerName, List<RegionInfo>>> loadOfAllTable) {
169  }
170
171  default void throttle(RegionPlan plan) throws Exception {
172    // noop
173  }
174}