/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.hbase.util; import java.io.IOException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.ReplicationPeerNotFoundException; import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.client.ConnectionFactory; import org.apache.hadoop.hbase.client.RegionReplicaUtil; import org.apache.hadoop.hbase.client.replication.ReplicationAdmin; import org.apache.hadoop.hbase.io.HFileLink; import org.apache.hadoop.hbase.io.Reference; import org.apache.hadoop.hbase.quotas.MasterQuotaManager; import org.apache.hadoop.hbase.regionserver.HRegion; import org.apache.hadoop.hbase.regionserver.StoreFileInfo; import org.apache.hadoop.hbase.replication.ReplicationException; import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.regionserver.RegionReplicaReplicationEndpoint; import org.apache.hadoop.hbase.zookeeper.ZKConfig; /** * Similar to {@link RegionReplicaUtil} but for the server side */ public class ServerRegionReplicaUtil extends RegionReplicaUtil { private static final Log LOG = LogFactory.getLog(ServerRegionReplicaUtil.class); /** * Whether asynchronous WAL replication to the secondary region replicas is enabled or not. * If this is enabled, a replication peer named "region_replica_replication" will be created * which will tail the logs and replicate the mutatations to region replicas for tables that * have region replication > 1. If this is enabled once, disabling this replication also * requires disabling the replication peer using shell or ReplicationAdmin java class. * Replication to secondary region replicas works over standard inter-cluster replication.ยท */ public static final String REGION_REPLICA_REPLICATION_CONF_KEY = "hbase.region.replica.replication.enabled"; private static final boolean DEFAULT_REGION_REPLICA_REPLICATION = false; private static final String REGION_REPLICA_REPLICATION_PEER = "region_replica_replication"; /** * Enables or disables refreshing store files of secondary region replicas when the memory is * above the global memstore lower limit. Refreshing the store files means that we will do a file * list of the primary regions store files, and pick up new files. Also depending on the store * files, we can drop some memstore contents which will free up memory. */ public static final String REGION_REPLICA_STORE_FILE_REFRESH = "hbase.region.replica.storefile.refresh"; private static final boolean DEFAULT_REGION_REPLICA_STORE_FILE_REFRESH = true; /** * The multiplier to use when we want to refresh a secondary region instead of flushing a primary * region. Default value assumes that for doing the file refresh, the biggest secondary should be * 4 times bigger than the biggest primary. */ public static final String REGION_REPLICA_STORE_FILE_REFRESH_MEMSTORE_MULTIPLIER = "hbase.region.replica.storefile.refresh.memstore.multiplier"; private static final double DEFAULT_REGION_REPLICA_STORE_FILE_REFRESH_MEMSTORE_MULTIPLIER = 4; /** * Returns the regionInfo object to use for interacting with the file system. * @return An HRegionInfo object to interact with the filesystem */ public static HRegionInfo getRegionInfoForFs(HRegionInfo regionInfo) { if (regionInfo == null) { return null; } return RegionReplicaUtil.getRegionInfoForDefaultReplica(regionInfo); } /** * Returns whether this region replica can accept writes. * @param region the HRegion object * @return whether the replica is read only */ public static boolean isReadOnly(HRegion region) { return region.getTableDesc().isReadOnly() || !isDefaultReplica(region.getRegionInfo()); } /** * Returns whether to replay the recovered edits to flush the results. * Currently secondary region replicas do not replay the edits, since it would * cause flushes which might affect the primary region. Primary regions even opened * in read only mode should replay the edits. * @param region the HRegion object * @return whether recovered edits should be replayed. */ public static boolean shouldReplayRecoveredEdits(HRegion region) { return isDefaultReplica(region.getRegionInfo()); } /** * Returns a StoreFileInfo from the given FileStatus. Secondary replicas refer to the * files of the primary region, so an HFileLink is used to construct the StoreFileInfo. This * way ensures that the secondary will be able to continue reading the store files even if * they are moved to archive after compaction * @throws IOException */ public static StoreFileInfo getStoreFileInfo(Configuration conf, FileSystem fs, HRegionInfo regionInfo, HRegionInfo regionInfoForFs, String familyName, Path path) throws IOException { // if this is a primary region, just return the StoreFileInfo constructed from path if (regionInfo.equals(regionInfoForFs)) { return new StoreFileInfo(conf, fs, path); } // else create a store file link. The link file does not exists on filesystem though. HFileLink link = HFileLink.build(conf, regionInfoForFs.getTable(), regionInfoForFs.getEncodedName(), familyName, path.getName()); if (StoreFileInfo.isReference(path)) { Reference reference = Reference.read(fs, path); return new StoreFileInfo(conf, fs, link.getFileStatus(fs), reference); } return new StoreFileInfo(conf, fs, link.getFileStatus(fs), link); } /** * Create replication peer for replicating to region replicas if needed. * @param conf configuration to use * @throws IOException */ public static void setupRegionReplicaReplication(Configuration conf) throws IOException { if (!isRegionReplicaReplicationEnabled(conf)) { return; } Admin admin = ConnectionFactory.createConnection(conf).getAdmin(); ReplicationPeerConfig peerConfig = null; try { peerConfig = admin.getReplicationPeerConfig(REGION_REPLICA_REPLICATION_PEER); } catch (ReplicationPeerNotFoundException e) { LOG.warn("Region replica replication peer id=" + REGION_REPLICA_REPLICATION_PEER + " not exist", e); } try { if (peerConfig == null) { LOG.info("Region replica replication peer id=" + REGION_REPLICA_REPLICATION_PEER + " not exist. Creating..."); peerConfig = new ReplicationPeerConfig(); peerConfig.setClusterKey(ZKConfig.getZooKeeperClusterKey(conf)); peerConfig.setReplicationEndpointImpl(RegionReplicaReplicationEndpoint.class.getName()); admin.addReplicationPeer(REGION_REPLICA_REPLICATION_PEER, peerConfig); } } finally { admin.close(); } } public static boolean isRegionReplicaReplicationEnabled(Configuration conf) { return conf.getBoolean(REGION_REPLICA_REPLICATION_CONF_KEY, DEFAULT_REGION_REPLICA_REPLICATION); } public static boolean isRegionReplicaWaitForPrimaryFlushEnabled(Configuration conf) { return conf.getBoolean(REGION_REPLICA_WAIT_FOR_PRIMARY_FLUSH_CONF_KEY, DEFAULT_REGION_REPLICA_WAIT_FOR_PRIMARY_FLUSH); } public static boolean isRegionReplicaStoreFileRefreshEnabled(Configuration conf) { return conf.getBoolean(REGION_REPLICA_STORE_FILE_REFRESH, DEFAULT_REGION_REPLICA_STORE_FILE_REFRESH); } public static double getRegionReplicaStoreFileRefreshMultiplier(Configuration conf) { return conf.getDouble(REGION_REPLICA_STORE_FILE_REFRESH_MEMSTORE_MULTIPLIER, DEFAULT_REGION_REPLICA_STORE_FILE_REFRESH_MEMSTORE_MULTIPLIER); } /** * Return the peer id used for replicating to secondary region replicas */ public static String getReplicationPeerId() { return REGION_REPLICA_REPLICATION_PEER; } }