在写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. T-SQL删除存储过程

    使用T-SQL脚本删除存储过程 语法: --声明数据库引用use 数据库名称;go --判断是否存在存储过程,如果存在则删除if exists(select * from sys.procedures ...

  2. 修改更新源sources.list,提高软件下载安装速度(2017.04.05)

    1.切换到root用户(如果已经是root用户就直接看第二步) dnt@HackerKali:~$ su 密码: 2.用文本编辑器打开sources.list,手动添加下面的更新源 root@Hack ...

  3. linux下export命令添加、删除环境变量(转载)

    转自:http://blog.csdn.net/shenshendeai/article/details/49794699 export命令 功能说明:设置或显示环境变量. 语 法:export [- ...

  4. Linux命令之chmod、chown

    一.chmod命令 chmod命令用于改变linux系统文件或目录的访问权限.用它控制文件或目录的访问权限.该命令有两种用法.一种是包含字母和操作符表达式的文字设定法:另一种是包含数字的数字设定法. ...

  5. Ex3_7无向图二部图_十一次作业

    (a) 从图中的某个顶点做深度优先遍历,并将不同层的顶点标记为红黑两种颜色,使得每条树边的两个顶点的颜色都不相同,如果遇到一条回边并且两个顶点的颜色都相同则说明图不是二部图. (b)如果存在一个长度为 ...

  6. kotlin学习笔记-异常好玩的list集合总结

    不积跬步无以至千里,不积小流无以成江海 先看看Kotlin中for循环的遍历 fun testList(){ var StringVal = "12_12_13_15_a_b_c_d_yu_ ...

  7. Oracle imp exp 导入导出 执行脚本

    一:用命令 imp/exp 的方式进行数据的导入和导出 一:文件后缀名: 二:oracle  导出 exp 命令 echo 开始备份数据库 if not exist D:\oracle_bak\fil ...

  8. 按照勾选 删除表格的行<tr>

    需求描述:有一个产品列表,有一个删减按钮,点击删减按钮,按照产品勾选的行,删除产品列表中对应的行数据 代码: //html代码<table id="table1"> & ...

  9. 【python】kafka在与celery和gevent连用时遇到的问题

    前提:kafka有同步,多线程,gevent异步和rdkafka异步四种模式.但是在与celery和gevent连用的时候,有的模式会出错. 下面是我代码运行的结果. 结论:使用多线程方式! 使用同步 ...

  10. 【kafka】生产者速度测试

    非常有用的参考博客:http://blog.csdn.net/qq_33160722/article/details/52903380 pykafka文档:http://pykafka.readthe ...