Hbase的写入负载均衡
在写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的写入负载均衡的更多相关文章
- 剖析HBase负载均衡和性能指标
1.概述 在分布式系统中,负载均衡是一个非常重要的功能,在HBase中通过Region的数量来实现负载均衡,HBase中可以通过hbase.master.loadbalancer.class来实现自定 ...
- 强大核心功能矩阵,详解腾讯云负载均衡CLB高可靠高性能背后架构
1 前言 腾讯云负载均衡(Cloud LoadBalancer),简称CLB, 负载均衡通过设置虚拟服务地址(VIP)将来自客户端的请求按照指定方式分发到其关联的多台后端云服务器,服务器将请求的响应返 ...
- HBase rebalance 负载均衡源码角度解读使用姿势
关键词:hbase rebalance 负载均衡 参考源码版本:apache-hbase-1.1.2 什么是HBase Rebalance ? 随着数据写入越来越多以及不均衡,即使一开始每个Regio ...
- HBASE数据模型&扩展和负载均衡理论
示例数据模型 HBase中扩展和负载均衡的基本单元成为region,region本质上是以行健排序的连续存储区间.如果region太大,系统会把它们 自动拆分,相反的,就是把多个region合并,以减 ...
- Hbase负载均衡流程以及源码
hmater负责把region均匀到各个region server .hmaster中有一个线程任务是专门处理负责均衡的,默认每隔5分钟执行一次. 每次负载均衡操作可以分为两步: 生成负载均衡计划表 ...
- 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 ...
- HBase流量限制和表负载均衡剖析
1.概述 在HBase-1.1.0之前,HBase集群中资源都是全量的.用户.表这些都是没有限制的,看似完美实则隐患较大.今天,笔者就给大家剖析一下HBase的流量限制和表的负载均衡. 2.内容 也许 ...
- hbase源码系列(一)Balancer 负载均衡
看源码很久了,终于开始动手写博客了,为什么是先写负载均衡呢,因为一个室友入职新公司了,然后他们遇到这方面的问题,某些机器的硬盘使用明显比别的机器要多,每次用hadoop做完负载均衡,很快又变回来了. ...
- 深度剖析HBase负载均衡和性能指标
深度剖析HBase负载均衡和性能指标 在分布式系统中,负载均衡是一个非常重要的功能,HBase通过Region的数量实现负载均衡,即通过hbase.master.loadbalancer.class实 ...
随机推荐
- Java文件复制
主要是工作代码,无解释. /** * 将文件或文件夹source复制到dest * <br>目标文件检测: * <br> a.当文件不存在时:需要创建文件 * <br&g ...
- CANopen--实现双电机速度同步
图1 将上图图中左边的电机和右边的电机进行速度同步,右边的电机同步左边的电机速度.这里需要知道Copley的驱动中的速度环的输入输出情况.如下图所示,速度环限制器接收速度命令信号,经限制后,产生一限制 ...
- PYTHON深拷贝与浅拷贝
浅拷贝就是对引用的拷贝,深拷贝就是对对象的资源的拷贝 浅拷贝 浅拷贝仅仅复制了容器中元素的地址 赋值的原则 1.赋值是将一个对象的地址赋值给一个变量,让变量指向该地址( 旧瓶装旧酒 ). 2.修改不可 ...
- 安装fastDFS的依赖包fdfs_client报错解决方法
输入以下指令后再尝试安装 python3环境下输入: sudo apt-get install python3 python-dev python3-dev build-essential libss ...
- 将list集合转json
public static class DataHelper { /// /// js 序列化器 /// static JavaScriptSerializer jss = new JavaScrip ...
- Java希尔排序算法
希尔排序就是对直接插入排序的一个优化.比如有这么一种情况:对一个无序数组进行从小到大的排序,但是数组的最后一个位置的数是最小的,我们要把它挪到第一个位置,其他位置的都要往后移动,要是这个数组非常大,那 ...
- swift 实践- 13 -- UIStepper
import UIKit class ViewController: UIViewController { var stepper: UIStepper! var label: UILabel! ov ...
- java如何将一个List传入Oracle存储过程
注:本文来源于 深圳gg < java如何将一个List传入Oracle存储过程 > 一:数据库端建一个PL/SQL的数组. CREATE OR REPLACE TYPE tabl ...
- Android源码分析二 硬件抽象层(HAL)
一 什么是HAL HAL 可定义一个标准接口以供硬件供应商实现,这可让 Android 忽略较低级别的驱动程序实现.借助 HAL,您可以顺利实现相关功能,而不会影响或更改更高级别的系统.HAL 实现会 ...
- js之DOM对象三
一.JS中for循环遍历测试 for循环遍历有两种 第一种:是有条件的那种,例如 for(var i = 0;i<ele.length;i++){} 第二种:for (var i in ...