在写Hbase的时候,会担心数据分布在各个region上不均匀(与预分区无关);

这个时候可能想到的方式:hash、加盐等(当然是可以的,但是读取的时候咋办呢? 哪天写一个这样的文章)

本文采用新方式:

        <repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos</url>
</repository>
</repositories> <dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>1.2.1</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-server</artifactId>
<version>1.2.1</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>

代码:

HbaseBalancer:
package hbase_balance;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes; import java.io.IOException;
import java.util.*; /**
*
* 优化策略 : 在table级别,对多于平局值部分的region,采用最少region节点分配策略,替代 admin.balancer();
* 最终效果 : 在table级别,每个regionServer的region个数都在平均值上下
* balance region on table level
*/
public class HbaseBalancer { public static final String tableStr = "data1";
public static final String ZK_QUORUM = "hadoop01:2181,hadoop02:2181,hadoop03:2181"; public static final Integer BUCKETS_PER_NODE = 50;
public static void main(String[] args) throws IOException { Configuration config = HBaseConfiguration.create();
config.set(HConstants.ZOOKEEPER_QUORUM, ZK_QUORUM);
Connection conn = ConnectionFactory.createConnection(config); Admin admin = conn.getAdmin();
ClusterStatus clusterStatus = admin.getClusterStatus();
Collection<ServerName> hServers = clusterStatus.getServers(); System.out.println("region servers :");
Map<String,RegionServer> allRegionServers = new HashMap<String,RegionServer>(15);
// 根据region server创建 hostname 和regionServer的映射,对allRegionServers进行初始化
for(ServerName server : hServers){ RegionServer rs = new RegionServer();
rs.setServerName(server);
allRegionServers.put( server.getHostname(), rs ) ; String getHostAndPort = server.getHostAndPort();
String getHostname = server.getHostname(); Long startCode = server.getStartcode();
System.out.println(startCode +" "+getHostname +" " +getHostAndPort);
//List<HRegionInfo> regionInfos = admin.getOnlineRegions(server);
allRegionServers .put(server.getHostname(), rs);
} Table table = conn.getTable(TableName.valueOf(tableStr ));
// 获取region的位置信息
RegionLocator locator = conn.getRegionLocator(table.getName());
List<HRegionLocation> hRegionLocations= locator.getAllRegionLocations(); int avgCnt = (( int)hRegionLocations.size())/ hServers.size();
System.out.println("avgCnt :" + avgCnt);
System.out.println("hRegionLocations.size() :"+hRegionLocations.size());
System.out.println("hServers.size() :" + hServers.size());
List<HRegionLocation> toAssign = new ArrayList<HRegionLocation>(); // 当一个region server 的region的数量大于平均值的时候,保存需要进行重新分配的region System.out.println("=============== get Region Location end =============== ");
// 根据已有的regionLocation信息进行最大程度的分配到各自节点上
for (HRegionLocation hRegionLocation: hRegionLocations) {
String hostname =hRegionLocation.getHostname();
System.out.println("hostname :" + hostname);
// RegionServer rs = allRegionServers.getOrDefault(hostname , new RegionServer() );
// 上面预先创建的allRegionServers,已经进行初始化,保证这里不会取空值
RegionServer rs = allRegionServers.get(hostname);
System.out.println("rs.getRegions().size() :"+rs.getRegions().size());
if (rs.getRegions().size() == 0) {
rs.setServerName(hRegionLocation.getServerName());
System.out.println("hRegionLocation.getServerName() :"+hRegionLocation.getServerName());
}
if (rs.getRegions().size() < avgCnt) {
rs.addRegion(hRegionLocation.getRegionInfo().getRegionNameAsString());
} else {
toAssign.add(hRegionLocation);
}
//noinspection Since15
allRegionServers.putIfAbsent(hostname,rs); // move to rs.add
System.out.println(" one of the" + hRegionLocation.toString());
}
System.out.println("=============== get Region Location end =============== "); // get all table regions which need to move
// move to erery serve
System.out.println(" region reassign");
Iterator<HRegionLocation> assign = toAssign.iterator();
for (HRegionLocation assignRegion: toAssign) {
System.out.println("all need to reassign region " + assignRegion.toString());
}
System.out.println("=============== region reassign began ==============="); while (assign.hasNext()){
HRegionLocation region = assign.next();
ServerName sn = region.getServerName(); HRegionInfo regionInfo = region.getRegionInfo();
String getEncodedName = regionInfo.getEncodedName();
String sourceHostname = region.getHostname();
String sourceName = sn.getServerName(); Random rand = new Random();
//String destServerKey = allRegionServers.keySet().toArray()[rand .nextInt(toAssign.size())].toString();
String destServerKey = getMinRegionServer(allRegionServers);
RegionServer rs = allRegionServers.get(destServerKey);
if (rs.getRegions().size() > avgCnt ){
// 当所有的regionServer中的region个数大于 平均个数的是停止分配,保证每个节点的region的个数尽可能的平均分配到各个节点上,
// 不会导致最后每个regionServer的region 个数已经达到平均值,但是某些regionServer的region个数仍然> (avgCnt+ 1)
break;
}
System.out.println(" get region toAssign" + region);
String destServerName = rs.getServerName().getServerName();
admin.move(regionInfo.getEncodedNameAsBytes(),Bytes.toBytes(destServerName));
System.out.println(" reassign to " + destServerName);
rs.addRegion(regionInfo.getRegionNameAsString());
} System.out.println("=============== region reassign end ===============");
} /**
* 从regionserver中遍历得到最小的 region server 的hostname
* @param allRegionServers
* @return region server host name
*/
public static String getMinRegionServer(Map<String,RegionServer> allRegionServers ){
String key = "";
Integer cnt = Integer.MAX_VALUE ;
for (String hostname : allRegionServers.keySet() ) {
if ( allRegionServers.get(hostname).getRegions().size() < cnt ){
cnt = allRegionServers.get(hostname).getRegions().size();
key = hostname;
}
}
return key;
}
}
RegionServer:
package hbase_balance;

import org.apache.hadoop.hbase.ServerName;

import java.util.ArrayList;
import java.util.List; /**
* Created by angel;
*/
public class RegionServer { private ServerName serverName; private List<String> regions ; public RegionServer(){
super();
this.regions = new ArrayList<String>();
} public ServerName getServerName() {
return serverName;
} public void setServerName(ServerName serverName) {
this.serverName = serverName;
} public List<String> getRegions() {
return regions;
} public void setRegions(List<String> regions) {
this.regions = regions;
}
public void addRegion ( String region ) {
this.regions.add(region);
} }

Hbase的写入负载均衡的更多相关文章

  1. 剖析HBase负载均衡和性能指标

    1.概述 在分布式系统中,负载均衡是一个非常重要的功能,在HBase中通过Region的数量来实现负载均衡,HBase中可以通过hbase.master.loadbalancer.class来实现自定 ...

  2. 强大核心功能矩阵,详解腾讯云负载均衡CLB高可靠高性能背后架构

    1 前言 腾讯云负载均衡(Cloud LoadBalancer),简称CLB, 负载均衡通过设置虚拟服务地址(VIP)将来自客户端的请求按照指定方式分发到其关联的多台后端云服务器,服务器将请求的响应返 ...

  3. HBase rebalance 负载均衡源码角度解读使用姿势

    关键词:hbase rebalance 负载均衡 参考源码版本:apache-hbase-1.1.2 什么是HBase Rebalance ? 随着数据写入越来越多以及不均衡,即使一开始每个Regio ...

  4. HBASE数据模型&扩展和负载均衡理论

    示例数据模型 HBase中扩展和负载均衡的基本单元成为region,region本质上是以行健排序的连续存储区间.如果region太大,系统会把它们 自动拆分,相反的,就是把多个region合并,以减 ...

  5. Hbase负载均衡流程以及源码

    hmater负责把region均匀到各个region server .hmaster中有一个线程任务是专门处理负责均衡的,默认每隔5分钟执行一次. 每次负载均衡操作可以分为两步: 生成负载均衡计划表 ...

  6. MySQL主从复制与lvs+keepalived单点写入读负载均衡高可用实验【转】

    一.环境Master(主机A):192.168.1.1Slave(主机B) :192.168.1.2  W-VIP(写入)  :192.168.1.3 R-VIP(读取)  :192.168.1.4  ...

  7. HBase流量限制和表负载均衡剖析

    1.概述 在HBase-1.1.0之前,HBase集群中资源都是全量的.用户.表这些都是没有限制的,看似完美实则隐患较大.今天,笔者就给大家剖析一下HBase的流量限制和表的负载均衡. 2.内容 也许 ...

  8. hbase源码系列(一)Balancer 负载均衡

    看源码很久了,终于开始动手写博客了,为什么是先写负载均衡呢,因为一个室友入职新公司了,然后他们遇到这方面的问题,某些机器的硬盘使用明显比别的机器要多,每次用hadoop做完负载均衡,很快又变回来了. ...

  9. 深度剖析HBase负载均衡和性能指标

    深度剖析HBase负载均衡和性能指标 在分布式系统中,负载均衡是一个非常重要的功能,HBase通过Region的数量实现负载均衡,即通过hbase.master.loadbalancer.class实 ...

随机推荐

  1. docker简单入门之使用docker容器部署简单的java web开源项目jpress博客程序

    一.在centos7.3上安装docker 前置条件 x86_64-bit 系统 kernel 3.10+ .检查内核版本,返回的值大于3.10即可 [root@node1 ~]# uname -r ...

  2. 数据库中关于convert的参数学习(转化函数用法)

    该页面中的内容来之http://www.cnblogs.com/xionglee/articles/1444916.html,以前我一直不知道当中的1,2,3表示什么,现在才知道呀!style 格式: ...

  3. Laravel 5.2--如何让表单提交错误,不清空?

    控制器 public function store(Request $request) { $validator = Validator::make($request->all(), [ 'Su ...

  4. 04 if条件判断 流程控制

    条件判断 if 语法一: if 条件: # 条件成立时执行的子代码块 代码1 代码2 代码3 示例: sex='female' age=18 is_beautiful=True if sex == ' ...

  5. 分布式全文检索引擎之ElasticSearch

    一 什么是 ElasticSearch Elasticsearch 是一个分布式可扩展的实时搜索和分析引擎,一个建立在全文搜索引擎 Apache Lucene(TM) 基础上的搜索引擎.当然 Elas ...

  6. 帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)

    作为一名前端工程师,必须搞懂JS中的prototype.__proto__与constructor属性,相信很多初学者对这些属性存在许多困惑,容易把它们混淆,本文旨在帮助大家理清它们之间的关系并彻底搞 ...

  7. linux指定只显示(只打印)文件中的某几行(中间几行)

    [一]从第3000行开始,显示1000行.即显示3000~3999行 cat filename | tail -n +3000 | head -n 1000 [二]显示1000行到3000行 cat ...

  8. react轮播图----react-slick

    1.安装 npm install react-slick; //安装样式 npm install slick carousel; 再在App.css中引入 @import "~slick-c ...

  9. Java调用oracle存储过程通过游标返回临时表数据

    注:本文来源于 <  Java调用oracle存储过程通过游标返回临时表数据   > Java调用oracle存储过程通过游标返回临时表数据 项目开发过程中,不可避免的会用到存储过程返回结 ...

  10. Confluence 6 手动运行和修改

    手动运行一个任务 希望手动运行一个计划任务,进入计划任务的列表中,找到你希望手动运行的计划任务,在这个计划任务的边上选择 运行(Run).这个计划任务将会马上执行. 不是所有的计划任务都可以手动运行的 ...