HBase系列-合并Region

背景

随着接入的业务增多和单业务数据量的增大,hbase的region数量迅速增长。hbase中RegionServer管理的region数量是有上限建议的,参见 HBase系列-RegionServer管理region数量上限
如何应对region个数不断增加带来的风险成为面临的一个问题。
想到2决方案

  • 添加hbase集群的机器数量,从而减少每个RegionServer管理的region数量
  • 给hbase表添加压缩和TTL时间,减少hbase中存储的数据量,降低hbase spilte的概率,减缓region数量增长
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.RegionLocator;
import org.apache.hadoop.hbase.io.compress.Compression;
import org.apache.hadoop.hbase.util.Bytes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Author: huyisen@gmail.com
 * Date: 2018-10-18
 * Copyright © 2018 huyisen. All Rights Reserved.
 */
public class HBaseOperationMain {


    private static final Logger log = LoggerFactory.getLogger(HBaseOperationMain.class);

    private static final int DAY = 86400;
    private static final String CF = "info";
    private static final int MERGE_SIZE = 1024 * 5;

    /**
     * HBase 配置信息
     */
    private static Configuration config() {
        Configuration config = HBaseConfiguration.create();
        config.set("hbase.zookeeper.quorum", "your hbase.zookeeper.quorum");
        config.set("hbase.zookeeper.property.clientPort", "your hbase.zookeeper.property.clientPort");
        config.set("zookeeper.znode.parent", "your zookeeper.znode.parent");
        return config;
    }

    /**
     * 添加ttl和压缩后要手动majorCompact否者不会立刻生效
     */
    private static void majorCompact(TableName tableName) throws IOException {
        try (Connection connection = ConnectionFactory.createConnection(config())) {
            Admin admin = connection.getAdmin();
            admin.majorCompact(tableName);
        }
    }

    /**
     * 添加ttl和SNAPPY压缩
     */
    private static void compressions(TableName tableName) throws IOException {
        try (Connection connection = ConnectionFactory.createConnection(config());
             Admin admin = connection.getAdmin()) {
            if (admin.isTableEnabled(tableName)) {
                admin.disableTable(tableName);
            }
            HTableDescriptor htd = admin.getTableDescriptor(tableName);
            HColumnDescriptor hcd = htd.getFamily(Bytes.toBytes(CF));
            hcd.setCompressionType(Compression.Algorithm.SNAPPY);
            hcd.setTimeToLive(DAY * 30);
            admin.modifyColumn(tableName, hcd);
            admin.compact(tableName);
            if (admin.isTableDisabled(tableName)) {
                admin.enableTable(tableName);
            }
        }
    }

    /**
     * 获取没有添加压缩和TTL的表
     */
    private static List<TableName> getCompressions() throws IOException {
        List<TableName> compressions = new ArrayList<>();
        try (Connection connection = ConnectionFactory.createConnection(config());
             Admin admin = connection.getAdmin()) {
            TableName[] events = admin.listTableNames();
            for (TableName event : events) {
                HTableDescriptor htd = admin.getTableDescriptor(event);
                HColumnDescriptor hcd = htd.getFamily(Bytes.toBytes(CF));
                Compression.Algorithm ct = hcd.getCompactionCompressionType();
                int ttl = hcd.getTimeToLive();
                if (ct.compareTo(Compression.Algorithm.SNAPPY) != 0 || ttl == Integer.MAX_VALUE) {
                    compressions.add(event);
                }
            }
        }
        return compressions;
    }

    /**
     * merge 相邻的region对
     */
    private static void merge(List<Pair<HRegionInfo, HRegionInfo>> merges) throws IOException {
        try (Connection connection = ConnectionFactory.createConnection(config());
             Admin admin = connection.getAdmin()) {
            for (Pair<HRegionInfo, HRegionInfo> pair : merges) {
                log.info("merge regions [{}]~[{}]", pair.first.getRegionNameAsString(), pair.second.getRegionNameAsString());
                admin.mergeRegions(pair.first.getRegionName(), pair.second.getRegionName(), false);
            }
            log.info("merge region size={}", merges.size());
        }
    }

    /**
     * 获取需要merge的相邻region对
     */
    private static List<Pair<HRegionInfo, HRegionInfo>> getMerges(TableName tableName) throws IOException {
        Configuration configuration = config();
        List<HRegionInfo> rns = new ArrayList<>();
        List<Pair<HRegionInfo, HRegionInfo>> merges = new ArrayList<>();
        try (Connection connection = ConnectionFactory.createConnection(configuration);
             Admin admin = connection.getAdmin();
             RegionLocator regionLocator = connection.getRegionLocator(tableName)) {
            ClusterStatus clusterStatus = admin.getClusterStatus();
            for (HRegionLocation hrl : regionLocator.getAllRegionLocations()) {
                hrl.getServerName();
                HRegionInfo regionInfo = hrl.getRegionInfo();
                byte[] rn = regionInfo.getRegionName();
                RegionLoad rl = clusterStatus.getLoad(hrl.getServerName())
                        .getRegionsLoad()
                        .get(rn);
                int size = rl.getStorefileSizeMB();
                if (size <= MERGE_SIZE) {
                    rns.add(regionInfo);
                }
            }
            Set<String> rrn = new HashSet<>();
            for (int i = 0; i < rns.size() - 1; i++) {
                Pair<HRegionInfo, HRegionInfo> pair = new Pair<>();
                pair.first = rns.get(i);
                if (rrn.contains(pair.first.getRegionNameAsString())) {
                    continue;
                }
                for (HRegionInfo rn : rns) {
                    pair.second = rn;
                    String regionName = pair.second.getRegionNameAsString();
                    if (!rrn.contains(regionName) && Bytes.toString(pair.first.getEndKey()).equals(Bytes.toString(pair.second.getStartKey()))) {
                        merges.add(pair);
                        rrn.add(regionName);
                        break;
                    }
                }
            }
            return merges;
        }
    }

    static class Pair<F, S> {
        F first;
        S second;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值