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.util.List;
023import java.util.Map;
024import org.apache.hadoop.conf.Configuration;
025import org.apache.hadoop.hbase.ClusterMetrics;
026import org.apache.hadoop.hbase.ServerName;
027import org.apache.hadoop.hbase.Stoppable;
028import org.apache.hadoop.hbase.TableName;
029import org.apache.hadoop.hbase.client.RegionInfo;
030import org.apache.hadoop.hbase.conf.ConfigurationObserver;
031import org.apache.hadoop.hbase.master.balancer.ClusterInfoProvider;
032import org.apache.yetus.audience.InterfaceAudience;
033
034/**
035 * Makes decisions about the placement and movement of Regions across RegionServers.
036 * <p/>
037 * Cluster-wide load balancing will occur only when there are no regions in transition and according
038 * to a fixed period of a time using {@link #balanceCluster(Map)}.
039 * <p/>
040 * On cluster startup, bulk assignment can be used to determine locations for all Regions in a
041 * cluster.
042 * <p/>
043 * This class produces plans for the {@code AssignmentManager} to execute.
044 * <p/>
045 * About locking:
046 * <ul>
047 * <li>We will first call {@link #setClusterInfoProvider(ClusterInfoProvider)} and then
048 * {@link #initialize()} to initialize the balancer, and before calling {@link #initialize()}, we
049 * will never call any methods of this balancer. So these two methods do not need to be
050 * synchronized.</li>
051 * <li>The {@link #balanceCluster(Map)} method will use the {@link ClusterMetrics} which is set by
052 * {@link #updateClusterMetrics(ClusterMetrics)}, and also lots of configurations, which could be
053 * changed by {@link #onConfigurationChange(Configuration)}, so the easier way is to make these
054 * three methods synchronized. And since there will be only one balancing thread, this will not
055 * impact performance too much.</li>
056 * <li>The {@link #roundRobinAssignment(List, List)}, {@link #retainAssignment(Map, List)} and
057 * {@link #randomAssignment(RegionInfo, List)} could be called from multiple threads concurrently,
058 * so these three methods should not be synchronized, the implementation classes need to make sure
059 * that they are thread safe.</li>
060 * </ul>
061 */
062@InterfaceAudience.Private
063public interface LoadBalancer extends Stoppable, ConfigurationObserver {
064
065  // Used to signal to the caller that the region(s) cannot be assigned
066  // We deliberately use 'localhost' so the operation will fail fast
067  ServerName BOGUS_SERVER_NAME = ServerName.valueOf("localhost,1,1");
068
069  /**
070   * Config for pluggable load balancers.
071   * @deprecated since 3.0.0, will be removed in 4.0.0. In the new implementation, as the base load
072   *             balancer will always be the rs group based one, you should just use
073   *             {@link org.apache.hadoop.hbase.HConstants#HBASE_MASTER_LOADBALANCER_CLASS} to
074   *             config the per group load balancer.
075   */
076  @Deprecated
077  String HBASE_RSGROUP_LOADBALANCER_CLASS = "hbase.rsgroup.grouploadbalancer.class";
078
079  /**
080   * Set the current cluster status. This allows a LoadBalancer to map host name to a server
081   */
082  void updateClusterMetrics(ClusterMetrics metrics);
083
084  /**
085   * Set the cluster info provider. Usually it is just a wrapper of master.
086   */
087  void setClusterInfoProvider(ClusterInfoProvider provider);
088
089  /**
090   * Perform the major balance operation for cluster.
091   * @param loadOfAllTable region load of servers for all table
092   * @return a list of regions to be moved, including source and destination, or null if cluster is
093   *         already balanced
094   */
095  List<RegionPlan> balanceCluster(Map<TableName, Map<ServerName, List<RegionInfo>>> loadOfAllTable)
096    throws IOException;
097
098  /**
099   * Perform a Round Robin assignment of regions.
100   * @return Map of servername to regioninfos
101   */
102  @NonNull
103  Map<ServerName, List<RegionInfo>> roundRobinAssignment(List<RegionInfo> regions,
104    List<ServerName> servers) throws IOException;
105
106  /**
107   * Assign regions to the previously hosting region server
108   * @return List of plans
109   */
110  @NonNull
111  Map<ServerName, List<RegionInfo>> retainAssignment(Map<RegionInfo, ServerName> regions,
112    List<ServerName> servers) throws IOException;
113
114  /**
115   * Get a random region server from the list
116   * @param regionInfo Region for which this selection is being done.
117   */
118  ServerName randomAssignment(RegionInfo regionInfo, List<ServerName> servers) throws IOException;
119
120  /**
121   * Initialize the load balancer. Must be called after setters.
122   */
123  void initialize() throws IOException;
124
125  /**
126   * Marks the region as online at balancer.
127   */
128  void regionOnline(RegionInfo regionInfo, ServerName sn);
129
130  /**
131   * Marks the region as offline at balancer.
132   */
133  void regionOffline(RegionInfo regionInfo);
134
135  /**
136   * Notification that config has changed
137   */
138  @Override
139  void onConfigurationChange(Configuration conf);
140
141  /**
142   * If balancer needs to do initialization after Master has started up, lets do that here.
143   */
144  void postMasterStartupInitialize();
145
146  /* Updates balancer status tag reported to JMX */
147  void updateBalancerStatus(boolean status);
148
149  /**
150   * In some scenarios, Balancer needs to update internal status or information according to the
151   * current tables load
152   * @param loadOfAllTable region load of servers for all table
153   */
154  default void
155    updateBalancerLoadInfo(Map<TableName, Map<ServerName, List<RegionInfo>>> loadOfAllTable) {
156  }
157}