Hadoop 副本存储策略的源码修改和设置

Table of Contents

  • BlockPlacementPolicy
  • Hadoop 提供的 BlockPlacementPolicy 实现
  • BlockPlacementPolicyDefault 源码阅读
    • 首先
    • 处理favoredNodes
    • 三副本选择
    • 再到具体的选择
  • 源码阅读的几个注意
  • 修改HDFS默认的副本放置机制
  • RackAwareness 机架感知

大多数的叫法都是副本放置策略,实质上是HDFS对所有数据的位置放置策略,并非只是针对数据的副本。因此Hadoop的源码里有block replicator(configuration)、 BlockPlacementPolicy(具体逻辑源码)两种叫法。

主要用途:上传文件时决定文件在HDFS上存储的位置(具体到datanode上的具体存储介质,如具体到存储在哪块硬盘);rebalance、datanode退出集群、副本数量更改等导致数据移动的操作中,数据移动的具体位置。

BlockPlacementPolicy

BlockPlacementPolicy 作为虚基类提供了基本的接口,具体的子类重点实现下面 选择副本 、 验证副本放置是否满足要求 、 选择能够删除的副本 三个函数:

 /*** 核心的副本放置策略实现,返回副本放置数量的存储位置* **如果有效节点数量不够(少于副本数),返回尽可能多的节点,而非失败**** @param srcPath 上传文件的路径* @param numOfReplicas 除下面chosen参数里已经选择的datanode,还需要的副本数量* @param writer 写数据的机器, null if not in the cluster. 一般用于放置第一个副本以降低网络通信* @param chosen 已经选择的节点* @param returnChosenNodes 返回结果里是否包含chosen的datanode* @param excludedNodes 不选的节点* @param blocksize 块大小* @return 排序好的选择结果*/public abstract DatanodeStorageInfo[] chooseTarget(String srcPath,int numOfReplicas,Node writer,List<DatanodeStorageInfo> chosen,boolean returnChosenNodes,Set<Node> excludedNodes,long blocksize,BlockStoragePolicy storagePolicy);/*** 判断传入的放置方式是否符合要求*/abstract public BlockPlacementStatus verifyBlockPlacement(DatanodeInfo[] locs, int numOfReplicas);/*** 当副本数量较多时,选择需要删除的节点*/abstract public List<DatanodeStorageInfo> chooseReplicasToDelete(Collection<DatanodeStorageInfo> candidates, int expectedNumOfReplicas,List<StorageType> excessTypes, DatanodeDescriptor addedNode,DatanodeDescriptor delNodeHint);

Hadoop 提供的 BlockPlacementPolicy 实现

Hadoop提供了BlockPlacementPolicyDefault、BlockPlacementPolicyWithNodeGroup、AvailableSpaceBlockPlacementPolicy三种实现(hadoop 2.7.7)。

其中BlockPlacementPolicyDefault是默认三副本策略的实现:第一个副本尽可能放在写入数据的节点,第二个副本放在与第一个副本不在同一机架(rack)下的节点,第三个副本与第二副本放在同一个机架。

BlockPlacementPolicyWithNodeGroup中第一、二个副本和Default副本放置相同,第三个副本在第二个机架下选择不同node group的结点。AvailableSpaceBlockPlacementPolicy实现存储平衡。Hadoop3.1中还加入了BlockPlacementPolicyRackFaultTolerant将数据存储到更多的机架下,BlockPlacementPolicyWithUpgradeDomain使用默认的副本放置策略,但是3个副本选择的datanode都要有不同的upgrade domains(为了方便大集群中datanode的更新和重启、将结点分配给不同的upgrade domain)。

通过改变dfs.block.replicator.classname 能够选择具体的实现类,默认值为org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyDefault。(Hadoop 2.7.7下,貌似不同版本的Hadoop的命名还不一样,而且2.7.7默认的配置文件里还没有,需要在源码中查)

BlockPlacementPolicyDefault 源码阅读

  public abstract DatanodeStorageInfo[] chooseTarget(String srcPath,int numOfReplicas,Node writer,List<DatanodeStorageInfo> chosen,boolean returnChosenNodes,Set<Node> excludedNodes,long blocksize,BlockStoragePolicy storagePolicy);

chooseTarget函数实现了具体的三副本策略。各种特殊情况(如只有1个副本、datanode数量不够、集群拓扑不满足要求等)的考虑让代码看起来比较复杂,常规情况直接跟着调试代码走会跳过很多异常处理部分,便于裂解正常流程。

在副本的选择上用了各种带chooseTarget函数,注意有几个函数结果是通过参数传出而不是返回值。

主要实现思路:

  1. 各种变量初始化
  2. 考虑favoredNodes的放置
  3. 除满足条件的favoredNodes后的副本放置策略(三副本)
  4. 结果排序

首先

srcPath没有被考虑,被直接舍弃:

return chooseTarget(numOfReplicas, writer, chosenNodes, returnChosenNodes,excludedNodes, blocksize, storagePolicy, flags); // ignore srcPath

因此默认的副本放置策略,在同一文件包含多个block时,每个block的存储位置独立考虑,并非存储在同一datanode

处理favoredNodes

上传文件时可以指定favoredNodes(默认为空),首先对favoredNodes所在的节点判断是否合适。如果满足条件的节点数还低于副本数,则添加新的副本。

 // --------------Choose favored nodes ---------------// 从favored nodes中选择,在上传文件时可以指定List<DatanodeStorageInfo> results = new ArrayList<>();boolean avoidStaleNodes = stats != null&& stats.isAvoidingStaleDataNodesForWrite();int maxNodesAndReplicas[] = getMaxNodesPerRack(0, numOfReplicas);numOfReplicas = maxNodesAndReplicas[0];int maxNodesPerRack = maxNodesAndReplicas[1];chooseFavouredNodes(src, numOfReplicas, favoredNodes,favoriteAndExcludedNodes, blocksize, maxNodesPerRack, results,avoidStaleNodes, storageTypes);// ---------------如果满足要求的favored nodes数量不足-----------if (results.size() < numOfReplicas) {// Not enough favored nodes, choose other nodes, based on block// placement policy (HDFS-9393).numOfReplicas -= results.size();for (DatanodeStorageInfo storage : results) {// add localMachine and related nodes to favoriteAndExcludedNodesaddToExcludedNodes(storage.getDatanodeDescriptor(),favoriteAndExcludedNodes);}DatanodeStorageInfo[] remainingTargets =chooseTarget(src, numOfReplicas, writer,new ArrayList<DatanodeStorageInfo>(numOfReplicas), false,favoriteAndExcludedNodes, blocksize, storagePolicy, flags);for (int i = 0; i < remainingTargets.length; i++) {results.add(remainingTargets[i]);}}

三副本选择

实现逻辑在 chooseTargetInOrder(…) 函数中

// 第一个副本的选择
if (numOfResults == 0) {writer = chooseLocalStorage(writer, excludedNodes, blocksize,maxNodesPerRack, results, avoidStaleNodes, storageTypes, true).getDatanodeDescriptor();if (--numOfReplicas == 0) {return writer;}
}// 选择与第一个副本不在同一Rack下的第二个副本
final DatanodeDescriptor dn0 = results.get(0).getDatanodeDescriptor();
if (numOfResults <= 1) {chooseRemoteRack(1, dn0, excludedNodes, blocksize, maxNodesPerRack,results, avoidStaleNodes, storageTypes);if (--numOfReplicas == 0) {return writer;}
}// 第三个副本
if (numOfResults <= 2) {final DatanodeDescriptor dn1 = results.get(1).getDatanodeDescriptor();// 第一、二副本在同一Rack下时选第三个副本 // (前面的favoredNodes以及集群条件可能造成这种情况)if (clusterMap.isOnSameRack(dn0, dn1)) {chooseRemoteRack(1, dn0, excludedNodes, blocksize, maxNodesPerRack,results, avoidStaleNodes, storageTypes);} else if (newBlock){ // 正常情况,第二副本的localRack下选第三副本chooseLocalRack(dn1, excludedNodes, blocksize, maxNodesPerRack,results, avoidStaleNodes, storageTypes);} else {  // 其它的以外chooseLocalRack(writer, excludedNodes, blocksize, maxNodesPerRack,results, avoidStaleNodes, storageTypes);}if (--numOfReplicas == 0) {return writer;}
}// 如果副本数量还没到0,剩下的副本随机选择
chooseRandom(numOfReplicas, NodeBase.ROOT, excludedNodes, blocksize,maxNodesPerRack, results, avoidStaleNodes, storageTypes);
return writer;

再到具体的选择

选择具体的存储位置被上面包装到了 chooseRemoteRack 和 chooseLocalRack 两个函数。

实际调用时只是 chooseRandom 函数,在限定的rack下选择一个随机的节点。

源码阅读的几个注意

代码在直接阅读时各种跳,但主线思路比较明确。主要带来阅读困难的位置:

  1. 很多函数调用不是通过返回值传出结果,而是通过参数。
  2. 注意某些if后的return会直接返回结果,后面的代码不会被调用。
  3. 递归的形式多次调用同一个函数以选择多个副本。
  4. 很多代码为了避免一些特殊情况,可以暂时略过(如catch里的异常处理)。

修改HDFS默认的副本放置机制

可以选择直接复制或继承BlockPlacementPolicyDefault的实现,或者直接继承BlockPlacementPolicy类编写对应的接口具体实现。

将编译好的jar包放入$HADOOP_PREFIX/share/hadoop/common下(或者其它的Hadoop jar包路径)。

改变dfs.block.replicator.classname 为上面的实现类,要带包的名称。

RackAwareness 机架感知

Hadoop 并不能自动检测集群的机架状态,而是要预先设置机架的状态,通过脚本或java类将datanode的ip转换成具体的机架上的位置。

官方文档介绍了基本思路,虽然实现上介绍得不是太清楚,只要将输入的ip转换成"/rackNum"的形式即可。

https://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/RackAwareness.html

 Categories:cloud computing

 Tags:hadoop

任何程序错误,以及技术疑问或需要解答的,请添加

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/546978.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

fabric.js和高级画板

本文介绍fabric.js框架使用&#xff0c;以及使用fabricjs打造一个高级画板程序. 高级画板功能介绍 全局绘制颜色选择护眼模式、网格模式切换自由绘制画箭头画直线画虚线画圆/椭圆/矩形/直角三角形/普通三角形/等边三角形文字输入图片展示及相关移动、缩放等操作删除功能 &am…

不同网段通过静态路由实现互通,华为S5700交换机开启telnet远程指定IP登陆配置(强烈推荐)

首先,不同网段通过静态路由实现互通配置方法,参考不同网段通过静态路由实现互通 在以上基础上,还需要配置 一、配置S5700交换机。 1.交换机开启Telnet服务 <Huawei>system-view Enter system view, return user view with Ctrl+Z. [Huawei]sysname LSW4 [

Centos7.x Hadoop 3.x HDFS 写入文件

操作目的 1、在Linux环境下 编写HDFS写文件程序的java文件 2、编译并打包HDFS的写程序 3、执行HDFS的写程序 环境、工具说明 1、先搭建一个 Hadoop 的基础集群环境 参考&#xff1a;Hadoop集群搭建 2、JDK版本&#xff1a;jdk1.8 安装配置过程 3、工具&#xff1a;xshell5 4、…

不同网段通过静态路由实现互通,华为S5700交换机开启SSH远程指定IP登陆配置(强烈推荐)

首先,不同网段通过静态路由实现互通配置方法,参考不同网段通过静态路由实现互通 在以上基础上,还需要配置 一、配置S5700交换机。 1.交换机开启stelnet服务 <Huawei>system-view Enter system view, return user view with Ctrl+Z. [Huawei]sysname LSW4 [

图片人脸检测——OpenCV版(二)

图片人脸检测 人脸检测使用到的技术是OpenCV&#xff0c;上一节已经介绍了OpenCV的环境安装&#xff0c;点击查看. 功能展示 识别一种图上的所有人的脸&#xff0c;并且标出人脸的位置&#xff0c;画出人眼以及嘴的位置&#xff0c;展示效果图如下&#xff1a; 多张脸识别效果图…

wordpress for sae建站全过程

为什么80%的码农都做不了架构师&#xff1f;>>> 文章链接 http://www.brighttj.com/wordpress/use-wordpress-for-sae/ 里面详细的介绍了整个博客网站搭建的过程。多捧场。 转载于:https://my.oschina.net/saitjr/blog/197592

Tesseract Ocr文字识别

Tesseract的OCR引擎最先由HP实验室于1985年开始研发&#xff0c;至1995年时已经成为OCR业内最准确的三款识别引擎之一。2005年&#xff0c;Tesseract由美国内华达州信息技术研究所获得&#xff0c;并求诸于Google对Tesseract进行改进、消除Bug、优化工作。Tesseract目前已作为开…

jenkins用ssh agent插件在pipeline里实现scp和远程执行命令

现在ssh agent的认证&#xff0c;已不支持明文用户密码&#xff0c;而只能用加密方式实现。 所以我先在jenknis和nginx服务器之后&#xff0c;实现ssh免密码rsa证书登陆。 私钥放jenkins&#xff0c;公钥放nginx。然后&#xff0c;将私钥拿出来&#xff0c;后面要写入jenkins…

QT5 获取窗口、系统屏幕大小尺寸信息,Qt 获取控件位置坐标,屏幕坐标,相对父窗体坐标

一、QT5 获取窗口大小尺寸信息 QT窗口尺寸&#xff0c;窗口大小和大小改变引起的事件 QResizeEvent。 //窗口左上角的位置(含边框)qDebug() << this->frameGeometry().x() << this->frameGeometry().y() << ;//1qDebug() << this->x() <…

视频人脸检测——OpenCV版(三)

视频人脸检测是图片人脸检测的高级版本&#xff0c;图片检测详情点击查看我的上一篇《图片人脸检测——OpenCV版&#xff08;二&#xff09;》 实现思路&#xff1a; 调用电脑的摄像头&#xff0c;把摄像的信息逐帧分解成图片&#xff0c;基于图片检测标识出人脸的位置&#x…

JENKINS使用DOCKER运行PYTEST并且出ALLURE报告

背景 最近想做一个简单的pytest 测试&#xff0c;用allure出报告&#xff0c;结果发现网上的方法都是在windows上装jenkins,然后用jenkins跑一个本地的运行环境。这种做法明显很不2019年。于是我决定做一个在jenkins上使用docker运行pytest&#xff0c;然后再出allure报告的文…

zabbix企业应用之low level discovery监控mysql

之前介绍了使用zabbix监控固定3306端口的mysql&#xff08;文章地址为http://dl528888.blog.51cto.com/2382721/1346590&#xff09;&#xff0c;有个不好的地方是只能监控固定的3306端口&#xff0c;如果是非3306端口的话&#xff0c;需要修改模板&#xff0c;如果主机有多个m…

图片人脸检测——Dlib版(四)

上几篇给大家讲了OpenCV的图片人脸检测&#xff0c;而本文给大家带来的是比OpenCV更加精准的图片人脸检测Dlib库。 往期目录 视频人脸检测——Dlib版&#xff08;六&#xff09;OpenCV添加中文&#xff08;五&#xff09;图片人脸检测——Dlib版&#xff08;四&#xff09;视频…

kubernetes 实战 使用 nfs 作为动态 storageClass 存储

kubernetes 实战 使用 nfs 作为动态 storageClass 存储 概述 之前有介绍过 Kubernetes 实战 pv and pvc&#xff0c; 相信使用过的pv和pvc的同学或者有过虚拟化经验的人来说肯定会想到很多问题&#xff0c;比如每次申请 pvc 都需要手动添加pv&#xff0c;这岂不是太不方便了。那…

OpenCV环境搭建(一)

OpenCV环境搭建 环境搭建为OpenCV的python&#xff08;一下简称py&#xff09;开发环境搭建&#xff0c;建立在py3的环境和语法上实现的。 windows系统搭建 系统环境&#xff1a;windows 10 python 3.6 OpenCV 3.4.1 一、安装python python的安装之前在python自学笔记的项…

git+pylint实现python提交代码格式校验

环境&#xff1a;win10(64)&#xff0c;python3.7.1&#xff0c;git2.7.2&#xff0c;pylint-2.3.1&#xff0c;git_pylint_commit_hook-2.5.1 以上为当期搭建所用到的版本&#xff0c;有异常时方便查找问题。 安装pylint&#xff0c;pylint是一个单独可以对python文件进行格…

OpenCV添加中文(五)

OpenCV添加文字的方法putText(…)&#xff0c;添加英文是没有问题的&#xff0c;但如果你要添加中文就会出现“&#xff1f;&#xff1f;&#xff1f;”的乱码&#xff0c;需要特殊处理一下。 下文提供封装好的&#xff08;代码&#xff09;方法&#xff0c;供OpenCV添加中文使…

UpdatePanel的内容中出现自定义多语言运行异常

2019独角兽企业重金招聘Python工程师标准>>> 我们项目有双语要求&#xff0c;采用的是自定义符号控制。在页面加载时进行翻译。 在xml文件中有如下格式的配置 <items> <resource page"~/SalesAppeal/SalesAppealCO.aspx"> <item key"…

ELK开机自启动脚本

elasticsearch服务配置文件 cd /etc/init.dtouch elasticsearchchmod x elasticsearchvi elasticsearch并输入以下内容: #!bin/bash# chkconfig: 2345 21 89 # description: elasticsearch# JAVA_HOME/usr/lib/jvm/jdk1.8.0_91 ES_HOME/usr/local/elasticsearch-6.7.2 case…

使用Bazel编译报错ERROR: Unrecognized option: --experimental_repo_remote_exec解决方法

ERROR: Unrecognized option: --experimental_repo_remote_exec 一、问题&#xff1a; INFO: Options provided by the client:Inherited common options: --isatty1 --terminal_columns80 INFO: Reading rc options for version from /home/emadboctor/tensorflow/.bazelrc:I…