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实 ...
随机推荐
- mysql管理工具percona-toolkit-3简单使用介绍
安装percona-toolkit-3 # -.el6.x86_64.rpm :.el6 -y 1.pt-summary #显示和系统相关的基本信息: [root@master ~]# pt-summ ...
- VUE 浏览器关闭时清空localStorage
1. 概述 1.1 说明 vue项目中,为了解决页面刷新时vuex数据丢失问题,使用localStorage进行存储对应的vuex数据(判断对应localStorage是否为空,不为空则为vuex中数 ...
- 29)django-ORM连表结构
连表结构 一对多:models.ForeignKey(其他表) 多对多:models.ManyToManyField(其他表) 一对一:models.OneToOneField(其他表) 应用场景: ...
- Java对数
java对数 先看看Java源码里的对数函数(在Java.lang.Math里) 方法1:log() 作用:返回以自然常数e为底数的对数值 说明: e ≍ 2.71828 18284 59045 23 ...
- 大数据python词频统计之hdfs分发-cacheArchive
-cacheArchive也是从hdfs上进分发,但是分发文件是一个压缩包,压缩包内可能会包含多层目录多个文件 1.The_Man_of_Property.txt文件如下(将其上传至hdfs上) ha ...
- Javascript杂!
JavaScript 标准参考教程(alpha) javascript中的 Object.defineProperty()和defineProperties JS压缩混淆 ---- 雅虎YUI 在线 ...
- 左查询left join on简单总结
应用场景分析:(个人观点,欢迎小祖宗们指正补充) 适合存在父子关系的单表,以及多表的查询 话不多说上代码 代码:mapper里的sql 表名字段什么的本来是单独集中配置的,现在还原到sql中了 & ...
- PyCharm里面执行代码没问题,Jenkins执行时找不到第三方库
在PyCharm里面代码执行没问题 本地cmd执行也没问题 Jenkins执行时报错 原因是第三方库是用PyCharm安装的,后来在Jenkins服务器上用pip装好第三方库后,就可以执行了 再执行 ...
- Nginx详解十六:Nginx场景实践篇之缓存服务
缓存类型: 服务端缓存 代理缓存 客户端缓存 Nginx代理缓存 配置语法 使用之前需要先定义一个proxy_cache_path配置语法:proxy_cache_path path [levels= ...
- txt提取相同内容、不同内容
findstr >相同部分.txt findstr >%~n2多余部分.txt findstr >%~n1多余部分.txt