首先看一下选择复制源节点的源码:

/*** Parse the data-nodes the block belongs to and choose one,* which will be the replication source.** We prefer nodes that are in DECOMMISSION_INPROGRESS state to other nodes* since the former do not have write traffic and hence are less busy.* We do not use already decommissioned nodes as a source.* Otherwise we choose a random node among those that did not reach their* replication limits.  However, if the replication is of the highest priority* and all nodes have reached their replication limits, we will choose a* random node despite the replication limit.** In addition form a list of all nodes containing the block* and calculate its replication numbers.** @param block Block for which a replication source is needed* @param containingNodes List to be populated with nodes found to contain the *                        given block* @param nodesContainingLiveReplicas List to be populated with nodes found to*                                    contain live replicas of the given block* @param numReplicas NumberReplicas instance to be initialized with the *                                   counts of live, corrupt, excess, and*                                   decommissioned replicas of the given*                                   block.* @param priority integer representing replication priority of the given*                 block* @return the DatanodeDescriptor of the chosen node from which to replicate*         the given block*/@VisibleForTestingDatanodeDescriptor chooseSourceDatanode(Block block,List<DatanodeDescriptor> containingNodes,List<DatanodeStorageInfo>  nodesContainingLiveReplicas,NumberReplicas numReplicas,int priority) {containingNodes.clear();nodesContainingLiveReplicas.clear();DatanodeDescriptor srcNode = null;int live = 0;int decommissioned = 0;int corrupt = 0;int excess = 0;Collection<DatanodeDescriptor> nodesCorrupt = corruptReplicas.getNodes(block);for(DatanodeStorageInfo storage : blocksMap.getStorages(block)) {final DatanodeDescriptor node = storage.getDatanodeDescriptor();LightWeightLinkedSet<Block> excessBlocks =excessReplicateMap.get(node.getDatanodeUuid());int countableReplica = storage.getState() == State.NORMAL ? 1 : 0; if ((nodesCorrupt != null) && (nodesCorrupt.contains(node)))corrupt += countableReplica;else if (node.isDecommissionInProgress() || node.isDecommissioned())decommissioned += countableReplica;else if (excessBlocks != null && excessBlocks.contains(block)) {excess += countableReplica;} else {nodesContainingLiveReplicas.add(storage);live += countableReplica;}containingNodes.add(node);// Check if this replica is corrupt// If so, do not select the node as src nodeif ((nodesCorrupt != null) && nodesCorrupt.contains(node))continue;if(priority != UnderReplicatedBlocks.QUEUE_HIGHEST_PRIORITY&& node.getNumberOfBlocksToBeReplicated() >= maxReplicationStreams){continue; // already reached replication limit}if (node.getNumberOfBlocksToBeReplicated() >= replicationStreamsHardLimit){continue;}// the block must not be scheduled for removal on srcNodeif(excessBlocks != null && excessBlocks.contains(block))continue;// never use already decommissioned nodesif(node.isDecommissioned())continue;// we prefer nodes that are in DECOMMISSION_INPROGRESS state// 如果你是退役中的节点会被优先选择并把你赋值给srcNode,后期的判断就基本跳过DFSUtil.getRandom().nextBoolean(),因为在 if(srcNode.isDecommissionInProgress()) continue;直接continue了。if(node.isDecommissionInProgress() || srcNode == null) {srcNode = node;continue;}if(srcNode.isDecommissionInProgress())continue;// switch to a different node randomly// this to prevent from deterministically selecting the same node even// if the node failed to replicate the block on previous iterations// 这里主要是防止一直选相同节点,如果所遍历的node是退役中节点,不会走这个方法(在上层就continue了),如果某个待复制的block(正常块,不存在损坏超额等问题)所在的三个节点都是普通正常节点,那具体选择哪个node就完全随机了,虽然是个伪随机。if(DFSUtil.getRandom().nextBoolean())srcNode = node;}if(numReplicas != null)numReplicas.initialize(live, decommissioned, corrupt, excess, 0);return srcNode;}

读注释我们可以了解到在选择复制源节点的时候会遵循以下几个原则:

  1. 优先选择退役中的节点,因为其无写入请求,负载低
  2. 不选择已经退役完成的节点
  3. 如果datanode上要复制block的Queue size与target datanode没被选出之前待处理复制工作数之和未达到复制限制(<maxReplicationStreams,conf配置名为**dfs.namenode.replication.max-streams**,在nodelist中随机选择节点
  4. 如果datanode上要复制block的Queue size与target datanode没被选出之前待处理复制工作数之和达到复制限制(>=maxReplicationStreams),除非blockQueue是最高优先级的,会随机选择一台节点,否则会pass掉(代码中为continue)
  5. 如果datanode上要复制block的Queue size与target datanode没被选出之前待处理复制工作数之和达到复制硬限制(>=replicationStreamsHardLimit,conf配置为**dfs.namenode.replication.max-streams-hard-limit**),无论满足什么条件都会被pass

加快DN退役的三个参数

    <property><name>dfs.namenode.replication.max-streams</name><value>64</value></property><property><name>dfs.namenode.replication.max-streams-hard-limit</name><value>128</value></property><property><name>dfs.namenode.replication.work.multiplier.per.iteration</name><value>32</value></property>

这三个参数的默认数分别为:2,4,2

前两个参数在上面5个原则中已经提到,详细说一下第三个参数dfs.namenode.replication.work.multiplier.per.iteration,这个参数决定了可以从很多under replication blocks中选出多少个block准备进行复制。可以选出的block数与集群adminState处于live状态的datanode成正比
int blocksToProcess = numlive * this.blocksReplWorkMultiplier(就是这个参数dfs.namenode.replication.work.multiplier.per.iteration),如果线上有10个in service datanode 那默认就可以选出 10 * 2 = 20个block 准备进行replicate

这三个参数其实就是个限流参数
第三个参数相当于入口限流参数,决定了可以从under replication blocks 的集合中选出多少个blocks 加到复制队列中准备进行复制。
前两个参数相当于出口限流,他们是在遍历复制队列中的blocks时,决定是否给当前block一个srcNode(也可能返回null)。如果满足限流条件,srcNode=当前node;如果不满足就contiune,直到找到满足的node,如果所有node都不满足就返回null(如果返回null 该block是不会relicate的);

block优先级

block所在队列的优先级有5个,源码如下

   /** The total number of queues : {@value} */
// 共五个等级static final int LEVEL = 5;/** The queue with the highest priority: {@value} */
//最高优先级queue:这些blocks会被优先复制。只有一个副本的块或者这些块有0个live副本,1个副本在正在退役的节点.如果这些blocks所在的磁盘或者服务器出现问题,这些blocks有丢失风险。static final int QUEUE_HIGHEST_PRIORITY = 0;/** The queue for blocks that are way below their expected value : {@value} */
//第二优先级: 这些blocks的副本远低于他们所期望的值。目前意味着实际的比例时少于1/3,虽然这些blocks可能并没有风险,但是他们清楚地考虑到blocks重要性。static final int QUEUE_VERY_UNDER_REPLICATED = 1;/** The queue for "normally" under-replicated blocks: {@value} */
//第三优先级:这些blocks 也低于所期望值(同样处于复制状态的块),以及 实际:预期的比例 足够好(不少与1/3),以至于它们不需要进入队列static final int QUEUE_UNDER_REPLICATED = 2;/** The queue for blocks that have the right number of replicas,* but which the block manager felt were badly distributed: {@value}*/
//第四优先级:一个block满足要求的最小副本数,但是由于分布不充分,如果一个机架当机可能导致所有的副本丢失/下线static final int QUEUE_REPLICAS_BADLY_DISTRIBUTED = 3;/** The queue for corrupt blocks: {@value} */
//第五优先级:这适用于已损坏的块,并且当前有可用的非损坏副本(当前)。这里的策略是保持这些损坏的块被复制,但是给出不是更高优先级的块。static final int QUEUE_WITH_CORRUPT_BLOCKS = 4;

HDFS的DN退役以及如何加快DN退役速度相关推荐

  1. squid正反向代理-加快网站访问速度

    配置squid代理服务器加快网站访问速度 一:squid服务概述   Squid cache(简称为Squid)是一个流行的自由软件(GNU通用公共许可证)的代理服务器和Web缓存服务器.Squid有 ...

  2. 使用Nginx反向代理和proxy_cache缓存搭建CDN服务器加快Web访问速度

    碰到问题:移动用户访问web服务器www.osyunwei.com很慢 解决办法: 1.在移动机房放置一台nginx反向代理服务器 2.通过域名DNS智能解析,所有移动用户访问www.osyunwei ...

  3. linux 设置ssh并发度,在linux如何使用ControlPersist加快SSH连接速度的问题

    不经意间我们又来到了文章的学习,在众多学习中,我们的文章也许不起眼,但是想必大家都有很多问题吧,所以重要的下面我们就来讲解一下,大家一定要认真看奥!! Linux系统进行服务器配置管理迁移的时候,SS ...

  4. 转: 加快Android编译速度

    转: http://timeszoro.xyz/2015/11/25/%E5%8A%A0%E5%BF%ABandroid%E7%BC%96%E8%AF%91%E9%80%9F%E5%BA%A6/ 加快 ...

  5. 计算机开机太慢了,电脑开机速度慢怎么办?3分钟加快电脑开机速度

    日常生活中,我们会经常使用电脑.但电脑使用久了之后,速度就会变得越来越慢.尤其是开机速度,每次都需要很久才能开机.这种时候我们就需要对电脑进行优化,加快电脑开机速度.那么下面就让小编为大家带来3分钟加 ...

  6. win10搜索服务器文件慢,如何解决win10搜索速度很慢的情况呢?|win10加快系统搜索速度的方法...

    如何解决win10搜索速度很慢的情况呢?|win10加快系统搜索速度的方法 发布时间:2019-03-08 小编:yue 浏览数: 大家在使用win10系统时,都知道Win10系统自带有搜索功能,可以 ...

  7. win10搜索服务器文件慢,Win10系统怎么加快文件搜索速度

    Win10纯净版64位系统自带有文件搜索功能,这个功能可以快速查找硬盘中的文件,但是有些用户发现系统搜索文件的速度很慢,那么有什么办法可以加快文件搜索速度呢?针对这个问题,今天小编就来分享Win10系 ...

  8. windows下python视频加速调节_windows10系统如何加快视频音频播放速度

    因为工作需求,一位windows10系统用户想要在电脑中加快视频音频的播放速度,这该如何操作呢?其实,方法非常简单,我们只要借助软件Adobe Premiere Pro即可轻松解决.下面,就随小编看看 ...

  9. 计算机关机速度,win7系统如何加快电脑关机速度|win7快速关机的方法

    相信很多用户都会在意电脑的开机的速度,而对计算机进行各种优化来提高电脑的开机速度.而有些深度技术win7旗舰版用户的电脑关机的速度比开机速度慢很多,这是怎么回事呢?在win7系统如何加快电脑关机速度呢 ...

最新文章

  1. centos7 php安装
  2. mac book pro怎么安装python_Mac安装python细节
  3. OpenCV C++ 02 - Create a Blank Image Display
  4. oracle表名最大长度6,Oracle中表名的最大长度是多less?
  5. 秒懂物理计算机出题规划,57张动图, 让你秒懂高中物理原理! 考试次次拿第一
  6. pytorch 对特征进行mean_Pytorch的mean和std调查实例
  7. Mesh Slicer 切割人体的原理分析
  8. 非对称密码之DH密钥交换算法
  9. 【Appium】手机滑动swipe方法及如何进行坐标定位
  10. 论文投稿系列之Cover Letter写法(一)
  11. “米粉”心碎,小米还能继续“高端”吗?
  12. 气象数据下载网站(存档)
  13. 一个酒鬼有20美元,三美元可以买一瓶酒,三个空瓶子可以换一瓶酒
  14. 链表:两个链表的第一个重合节点
  15. 发一台数字控制稳压电源试试 测试IC等小功率低波纹高精度专用
  16. 五种常用的异常值检测方法(均方差、箱形图、DBScan 聚类、孤立森林、Robust Random Cut Forest
  17. 风电滑环 风力发电机滑环 导电环 集电环
  18. CAD图纸中插入或删除编号的图文教程
  19. CISCO路由器的ACL的各项设置
  20. qt 判断字符串中是否含有中文字符_Qt 中文字符串问题

热门文章

  1. 最AI 豆芽儿童机器人邀约图灵机器人创想未来
  2. 计算机存储系统之磁盘阵列技术
  3. 10月11号58同城面试的编程题
  4. 快速学习编程的10个关键技巧
  5. vue报错SassError: Expected newline.
  6. 明朝的那些事(随笔1)
  7. 家用计算机防火墙设置,电脑防火墙设置【解决思路】
  8. mysql 谓语提前,英语倒装句全倒装时什么时候要把did提前?这个老搞不清楚
  9. 谈谈现在低价U盘的质量问题
  10. 管理领英邮件类型和频率