一 Balancer regionCountCost 权重。
原文如下地址 :
http://www.cnblogs.com/cenyuhai/p/3650943.html
看源码很久了,终于开始动手写博客了,为什么是先写负载均衡呢,因为一个室友入职新公司了,然后他们遇到这方面的问题,某些机器的硬盘使用明显比别的机器要多,每次用hadoop做完负载均衡,很快又变回来了。
首先我们先看HMaster当中怎么初始化Balancer的,把集群的状态穿进去,设置master,然后执行初始化。
//initialize load balancerthis.balancer.setClusterStatus(getClusterStatus());
this.balancer.setMasterServices(this);
this.balancer.initialize();
然后调用是在HMaster的balance()方法当中调用

Map<TableName, Map<ServerName, List<HRegionInfo>>> assignmentsByTable =
this.assignmentManager.getRegionStates().getAssignmentsByTable(); List<RegionPlan> plans = new ArrayList<RegionPlan>();
//Give the balancer the current cluster state.this.balancer.setClusterStatus(getClusterStatus());
//针对表来做平衡,返回平衡方案,针对全局,可能不是最优解for (Map<ServerName, List<HRegionInfo>> assignments : assignmentsByTable.values()) {
List<RegionPlan> partialPlans = this.balancer.balanceCluster(assignments);
if (partialPlans != null) plans.addAll(partialPlans);
}

可以看到它首先获取了当前的集群的分配情况,这个分配情况是根据表的 Map<TableName, Map<ServerName, List<HRegionInfo>>,然后遍历这个map的values,调用 balancer.balanceCluster(assignments) 来生成一个partialPlans,生成RegionPlan(Region的移动计划) 。
我们就可以切换到StochasticLoadBalancer当中了,这个是默认Balancer具体的实现了,也是最好的实现,下面就说说这玩意儿咋实现的。
看一下注释,这个玩意儿吹得神乎其神的,它说它考虑到了这么多因素:

* <ul>
* <li>Region Load</li> Region的负载
* <li>Table Load</li> 表的负载
* <li>Data Locality</li> 数据本地性
* <li>Memstore Sizes</li> 内存Memstore的大小
* <li>Storefile Sizes</li> 硬盘存储文件的大小
* </ul>

好,我们从balanceCluster开始看吧,一进来第一件事就是判断是否需要平衡
//不需要平衡就退出if (!needsBalance(new ClusterLoadState(clusterState))) {
return null;
}
平衡的条件是:负载最大值和最小值要在平均值(region数/server数)的+-slop值之间, 但是这个平均值是基于表的,因为我们传进去的参数clusterState就是基于表的。

// Check if we even need to do any load balancing// HBASE-3681 check sloppiness firstfloat average = cs.getLoadAverage(); // for logging//集群的负载最大值和最小值要在平均值的+-slop值之间int floor = (int) Math.floor(average * (1 - slop));
int ceiling = (int) Math.ceil(average * (1 + slop));
if (!(cs.getMinLoad() > ceiling || cs.getMaxLoad() < floor)) {
.....return false;
}
return true;

如果需要平衡的话,就开始计算开销了

// Keep track of servers to iterate through them.
Cluster cluster = new Cluster(clusterState, loads, regionFinder);
//计算出来当前的开销 double currentCost = computeCost(cluster, Double.MAX_VALUE);
double initCost = currentCost;
double newCost = currentCost;
for (step = 0; step < computedMaxSteps; step++) {
//随机挑选一个"选号器"
int pickerIdx = RANDOM.nextInt(pickers.length);
RegionPicker p = pickers[pickerIdx];
//用选号器从集群当中随机跳出一对来,待处理的<server,region>对
Pair<Pair<Integer, Integer>, Pair<Integer, Integer>> picks = p.pick(cluster);
int leftServer = picks.getFirst().getFirst();
int leftRegion = picks.getFirst().getSecond();
int rightServer = picks.getSecond().getFirst();
int rightRegion = picks.getSecond().getSecond();
cluster.moveOrSwapRegion(leftServer,
rightServer,
leftRegion,
rightRegion);
//移动或者交换完之后,看看新的开销是否要继续
newCost = computeCost(cluster, currentCost);
// Should this be kept? 挺好,保存新状态
if (newCost < currentCost) {
currentCost = newCost;
} else {
// 操作不划算,就回退
cluster.moveOrSwapRegion(leftServer,
rightServer,
rightRegion,
leftRegion);
}
if (initCost > currentCost) {
//找到了满意的平衡方案
List<RegionPlan> plans = createRegionPlans(cluster);
return plans;
}

上面的被我清除了细枝末节之后的代码主体,okay,上面逻辑过程如下:
1. 生成一个虚拟的集群cluster,方便计算计算当前状态的开销,其中clusterState是表的状态,loads是整个集群的状态。
// Keep track of servers to iterate through them.
Cluster cluster = new Cluster(clusterState, loads, regionFinder);
//计算出来当前的开销 double currentCost = computeCost(cluster, Double.MAX_VALUE);
double initCost = currentCost;
double newCost = currentCost;
2. 然后循环 computedMaxSteps次,随机从选出一个picker来计算平衡方案
int pickerIdx = RANDOM.nextInt(pickers.length);
RegionPicker p = pickers[pickerIdx];
//用选号器从集群当中随机跳出一对来,待处理的<server,region>对
Pair<Pair<Integer, Integer>, Pair<Integer, Integer>> picks = p.pick(cluster);
picker是啥?这里面有三个,第一个是RandomRegionPicker是随机挑选region,这里就不详细介绍了,主要讨论后面两个;第二个LoadPicker是计算负载的,第三个主要是考虑本地性的。
给我感觉就很像ZF的摇号器一样,用哪种算法还要摇个号
pickers = new RegionPicker[] {
new RandomRegionPicker(),
new LoadPicker(),
localityPicker
};
下面我们先看localityPicker的pick方法,这个方法是随机抽选出来一个server、region,找出region的其他本地机器,然后他们返回。

@Override
Pair<Pair<Integer, Integer>, Pair<Integer, Integer>> pick(Cluster cluster) {
if (this.masterServices == null) {
return new Pair<Pair<Integer, Integer>, Pair<Integer, Integer>>(
new Pair<Integer, Integer>(-1,-1),
new Pair<Integer, Integer>(-1,-1)
);
}
// Pick a random region server 随机选出一个server来 int thisServer = pickRandomServer(cluster); // Pick a random region on this server 随机选出region int thisRegion = pickRandomRegion(cluster, thisServer, 0.0f); if (thisRegion == -1) {
return new Pair<Pair<Integer, Integer>, Pair<Integer, Integer>>(
new Pair<Integer, Integer>(-1,-1),
new Pair<Integer, Integer>(-1,-1)
);
} // Pick the server with the highest locality 找出本地性最高的目标server int otherServer = pickHighestLocalityServer(cluster, thisServer, thisRegion); // pick an region on the other server to potentially swap int otherRegion = this.pickRandomRegion(cluster, otherServer, 0.5f); return new Pair<Pair<Integer, Integer>, Pair<Integer, Integer>>(
new Pair<Integer, Integer>(thisServer,thisRegion),
new Pair<Integer, Integer>(otherServer,otherRegion)
);
}

okay,这个结束了,下面我们看看LoadPicker吧。

@Override
Pair<Pair<Integer, Integer>, Pair<Integer, Integer>> pick(Cluster cluster) {
cluster.sortServersByRegionCount();
//先挑选出负载最高的serverint thisServer = pickMostLoadedServer(cluster, -1);
//再选出除了负载最高的server之外负载最低的serverint otherServer = pickLeastLoadedServer(cluster, thisServer); Pair<Integer, Integer> regions = pickRandomRegions(cluster, thisServer, otherServer);
return new Pair<Pair<Integer, Integer>, Pair<Integer, Integer>>(
new Pair<Integer, Integer>(thisServer, regions.getFirst()),
new Pair<Integer, Integer>(otherServer, regions.getSecond()) );
}

这里的负载高和负载低是按照Server上面的region数来算的,而不是存储文件啥的,选出负载最高和负载最低的时候,又随机抽出region来返回了。
pick挑选的过程介绍完了,那么很明显,计算才是重头戏了,什么样的region会导致计算出来的分数高低呢?
3. 重点在计算函数上 computeCost(cluster, Double.MAX_VALUE) 结果这个函数也超级简单,哈哈

protected double computeCost(Cluster cluster, double previousCost) {
double total = 0; for (CostFunction c:costFunctions) {
if (c.getMultiplier() <= 0) {
continue;
} total += c.getMultiplier() * c.cost(cluster); if (total > previousCost) {
return total;
}
}
return total;
}

遍历CostFunction,拿cost的加权平均和计算出来。
那costFunction里面都有啥呢?localityCost又出现了,看来本地性是一个很大的考虑的情况。

costFunctions = new CostFunction[]{
new RegionCountSkewCostFunction(conf),
new MoveCostFunction(conf),
localityCost,
new TableSkewCostFunction(conf),
regionLoadFunctions[0],
regionLoadFunctions[1],
regionLoadFunctions[2],
regionLoadFunctions[3],
};
regionLoadFunctions = new CostFromRegionLoadFunction[] {
new ReadRequestCostFunction(conf),
new WriteRequestCostFunction(conf),
new MemstoreSizeCostFunction(conf),
new StoreFileCostFunction(conf)
};

可以看出来,里面真正看中硬盘内容大小的,只有一个StoreFileCostFunction,cost的计算方式有些区别,但都是一个0-1之间的数字,下面给出里面5个函数都用过的cost的函数。

//cost函数double max = ((count - 1) * mean) + (total - mean);
for (double n : stats) {
double diff = Math.abs(mean - n);
totalCost += diff;
} double scaled = scale(0, max, totalCost);
return scaled; //scale函数protected double scale(double min, double max, double value) {
if (max == 0 || value == 0) {
return 0;
} return Math.max(0d, Math.min(1d, (value - min) / max));
}

经过分析吧,我觉得影响里面最后cost最大的是它的权重,下面给一下,这些function的默认权重。
RegionCountSkewCostFunction hbase.master.balancer.stochastic.regionCountCost ,默认值500 MoveCostFunction hbase.master.balancer.stochastic.moveCost,默认值是100 localityCost hbase.master.balancer.stochastic.localityCost,默认值是25
TableSkewCostFunction hbase.master.balancer.stochastic.tableSkewCost,默认值是35 ReadRequestCostFunction hbase.master.balancer.stochastic.readRequestCost,默认值是5 WriteRequestCostFunction hbase.master.balancer.stochastic.writeRequestCost,默认值是5 MemstoreSizeCostFunction hbase.master.balancer.stochastic.memstoreSizeCost,默认值是5 StoreFileCostFunction hbase.master.balancer.stochastic.storefileSizeCost,默认值是5
Storefile的默认值是5,那么低。。。可以试着提高一下这个参数,使它在计算cost消耗的时候,产生更加正向的意义,效果不好说。
4. 根据虚拟的集群状态生成RegionPlan,这里就不说了
List<RegionPlan> plans = createRegionPlans(cluster);
源码的分析完毕,要想减少存储内容分布不均匀,可以试着考虑增加一个picker,这样又不会缺少对其他条件的考虑,具体可以参考 LoadPicker,复制它的实现再写一个,在pickMostLoadedServer和pickLeastLoadedServer这两个方法里面把考虑的条件改一下,以前的条件是Integer[] servers = cluster.serverIndicesSortedByRegionCount; 通过这个来查找一下负载最高和最低的server,那么现在我们要在Cluster里面增加一个Server ---> StoreFile大小的关系映射集合,但是这里面没有,只有regionLoads,RegionLoad这个类有一个方法 getStorefileSizeMB可以获得StoreFile的大小,我们通过里面的region和server的映射 regionIndexToServerIndex来最后计算出来这个映射关系即可,这个计算映射关系个过程放在Cluster的构造函数里面。
一 Balancer regionCountCost 权重。的更多相关文章
- 2.【Spring Cloud Alibaba】实现负载均衡-Ribbon
负载均衡的两种方式 如何实现负载均衡 目前已经实现让A总能找到B,如何实现负载均衡 负载均衡的两种方式 服务器端负载均衡 客户端负载均衡 使用Ribbo实现负载均衡 Ribbon是什么 ==Netfl ...
- Redis分布式锁 (图解-秒懂-史上最全)
文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...
- hbase源码系列(一)Balancer 负载均衡
看源码很久了,终于开始动手写博客了,为什么是先写负载均衡呢,因为一个室友入职新公司了,然后他们遇到这方面的问题,某些机器的硬盘使用明显比别的机器要多,每次用hadoop做完负载均衡,很快又变回来了. ...
- go微服务框架kratos学习笔记七(kratos warden 负载均衡 balancer)
目录 go微服务框架kratos学习笔记七(kratos warden 负载均衡 balancer) demo demo server demo client 池 dao service p2c ro ...
- Azure Load Balancer(一) 为我们的Web项目提供负载均衡
一,引言 上节,我们讲到使用 Azure Traffic Manager 为我们的 Demo 项目提供负载均衡,以及流量转发的功能.但是Azure 提供类似的功能的服务远远不止这一个,今天我们就来讲一 ...
- Azure Load Balancer(二) 基于内部的负载均衡来转发为访问请求
一,引言 上一节,我们使用 Azure Load Balancer 类型为外部的,来转发我们的 Web 服务.今天我们看看另一种类型为 “Internal” 的 Azure Load Balancer ...
- 前端极易被误导的css选择器权重计算及css内联样式的妙用技巧
记得大学时候,专业课的网页设计书籍里面讲过css选择器权重的计算:id是100,class是10,html标签是5等等,然后全部加起来的和进行比较... 我只想说:真是误人子弟,害人不浅! 最近,在前 ...
- SEO:权重如何做到从0到1
SEO:权重如何做到从0到1 [写于2016年9月]我真的好久好久没到我的博客上去看过了,今天突然登上 seo.chinaz.com,搜索 dkplus.iteye.com,发现自己的博客在百度收录中 ...
- CSS选择器的权重与优先规则?
我们做项目的时候,经常遇到样式层叠问题,被其他的样式覆盖,或者写的权重不高没效果,对权重没有具体的分析,做了一个总结. css继承是从一个元素向其后代元素传递属性值所采用的机制.确定应当向一个元素应用 ...
随机推荐
- Activiti 23张表及7大服务详解
7大服务介绍 服务名称 描述 RepositoryService Activiti 中每一个不同版本的业务流程的定义都需要使用一些定义文件,部署文件和支持数据 ( 例如 BPMN2.0 XML 文件, ...
- POJ 2367 Genealogical tree【拓扑排序】
题意:大概意思是--有一个家族聚集在一起,现在由家族里面的人讲话,辈分高的人先讲话.现在给出n,然后再给出n行数 第i行输入的数表示的意思是第i行的子孙是哪些数,然后这些数排在i的后面. 比如样例 5 ...
- 利用php的GD库生成验证码
<?php ,); //创建一个100宽30高的底图,默认黑色 ,,); //修改颜色.数字对应 rgb 的三个数值.白色 imagefill(,,$bgcolor); //从左上角到右下角把颜 ...
- linux查看系统cpu信息
# 查看物理CPU个数 cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l # 查看每个物理CPU中core的个数(即 ...
- centos7 安装freeswitch
1.安装运行库 yum install -y git gcc-c++ wget alsa-lib-devel autoconf automake bison broadvoice-devel bzip ...
- 单机Mongo复制集安装配置(数据库版本:4.x)
官方文档: https://docs.mongodb.com/manual/tutorial/deploy-replica-set-with-keyfile-access-control/#dep ...
- 紫书 习题 8-20 UVa 1620 (找规律+求逆序对)
这道题看了半天没看出什么规律, 然后看到别人的博客, 结论是当n为奇数且逆序数为奇数的时候 无解, 否则有解.但是没有给出证明, 在网上也找到详细的证明--我也不知道是为什么-- 求逆序对有两种方法, ...
- Linux shell 内部变量
1 TMOUT 来自bash的解释: If set to a value greater than zero, TMOUT is treated as the default timeout for ...
- BEGINNING SHAREPOINT® 2013 DEVELOPMENT 第1章节--SharePoint 2013 介绍 处理开发者需求
BEGINNING SHAREPOINT® 2013 DEVELOPMENT 第1章节--SharePoint 2013 介绍 处理开发者需求 SharePoint本质上是一个平台.你 ...
- UItableView中的一些方法
有关UITableView的知识点相对照较简单,一些简单的经常使用的方法有时间在写上: 以下的几个方法假设仅仅是展示UITableView是用不到的,须要对对应的区段进行操作的时候才会用到. 方法例如 ...