ReplicationMonitor是HDFS中关于数据块复制的监控线程,它的主要作用就是计算DataNode工作,并将复制请求超时的块重新加入到待调度队列。其定义及作为线程核心的run()方法如下:

  1. /**
  2. * Periodically calls computeReplicationWork().
  3. * 周期性调用computeReplicationWork()方法
  4. */
  5. private class ReplicationMonitor implements Runnable {
  6. @Override
  7. public void run() {
  8. // 如果namesystem持续运行,while循环一直进行
  9. while (namesystem.isRunning()) {
  10. try {
  11. // Process replication work only when active NN is out of safe mode.
  12. if (namesystem.isPopulatingReplQueues()) {
  13. // 计算数据节点工作
  14. computeDatanodeWork();
  15. // 将复制请求超时的块重新加入到待调度队列
  16. processPendingReplications();
  17. }
  18. // 线程休眠replicationRecheckInterval时间
  19. Thread.sleep(replicationRecheckInterval);
  20. } catch (Throwable t) {
  21. if (!namesystem.isRunning()) {
  22. LOG.info("Stopping ReplicationMonitor.");
  23. if (!(t instanceof InterruptedException)) {
  24. LOG.info("ReplicationMonitor received an exception"
  25. + " while shutting down.", t);
  26. }
  27. break;
  28. } else if (!checkNSRunning && t instanceof InterruptedException) {
  29. LOG.info("Stopping ReplicationMonitor for testing.");
  30. break;
  31. }
  32. LOG.fatal("ReplicationMonitor thread received Runtime exception. ", t);
  33. terminate(1, t);
  34. }
  35. }
  36. }
  37. }

ReplicationMonitor线程的run()方法运行逻辑比较清晰,如果namesystem持续运行,while循环一直进行,在这个循环内,仅当活跃NN不在安全模式时才会进行复制工作:

1、调用computeDatanodeWork()方法计算数据节点工作;

2、调用processPendingReplications()方法将复制请求超时的块重新加入到待调度队列

3、线程休眠replicationRecheckInterval时间后继续运行。

首先说下这个replicationRecheckInterval,它是名字节点检查新的复制工作的时间间隔,其初始化在BlockManager的构造函数中,代码如下:

  1. this.replicationRecheckInterval =
  2. conf.getInt(DFSConfigKeys.DFS_NAMENODE_REPLICATION_INTERVAL_KEY,
  3. DFSConfigKeys.DFS_NAMENODE_REPLICATION_INTERVAL_DEFAULT) * 1000L;

其取值取参数dfs.namenode.replication.interval,参数未配置的话,默认为3秒。

再来看下计算数据节点工作的computeDatanodeWork()方法,它负责计算块复制、块无效工作可以被调度到数据节点的总数,数据节点将在接下来的心跳中被指派该工作,并返回被调度的复制或移除的块的数目,代码如下:

  1. /**
  2. * Compute block replication and block invalidation work that can be scheduled
  3. * on data-nodes. The datanode will be informed of this work at the next
  4. * heartbeat.
  5. *
  6. * 计算块复制、块无效工作可以被调度到数据节点的总数。数据节点将在接下来的心跳中被指派该工作。
  7. * 返回被调度的复制或移除的块的数目
  8. *
  9. * @return number of blocks scheduled for replication or removal.
  10. */
  11. int computeDatanodeWork() {
  12. // Blocks should not be replicated or removed if in safe mode.
  13. // It's OK to check safe mode here w/o holding lock, in the worst
  14. // case extra replications will be scheduled, and these will get
  15. // fixed up later.
  16. / 如果namesystem处于安全模式,直接返回0
  17. if (namesystem.isInSafeMode()) {
  18. return 0;
  19. }
  20. // 通过心跳管理器heartbeatManager获取存活数据节点数
  21. final int numlive = heartbeatManager.getLiveDatanodeCount();
  22. // blocksReplWorkMultiplier为集群每个周期每个DataNode平均待复制的数据块数量,
  23. // blocksToProcess为每个周期集群需要复制的数据块数量
  24. final int blocksToProcess = numlive
  25. * this.blocksReplWorkMultiplier;
  26. // blocksInvalidateWorkPct为集群每个周期每个DataNode平均待删除的无效数据块百分比
  27. // nodesToProcess为集群每个周期待删除的无效数据块数量
  28. final int nodesToProcess = (int) Math.ceil(numlive
  29. * this.blocksInvalidateWorkPct);
  30. // 计算复制工作量workFound
  31. int workFound = this.computeReplicationWork(blocksToProcess);
  32. // Update counters
  33. // namesystem加写锁
  34. namesystem.writeLock();
  35. try {
  36. // 调用updateState()方法更新相关状态
  37. this.updateState();
  38. // 将计算得到的复制工作量workFound赋值给被调度复制的数据块数scheduledReplicationBlocksCount
  39. this.scheduledReplicationBlocksCount = workFound;
  40. } finally {
  41. // namesystem释放写锁
  42. namesystem.writeUnlock();
  43. }
  44. // 计算删除无效块工作量,并累加到workFound
  45. workFound += this.computeInvalidateWork(nodesToProcess);
  46. // 返回总工作量workFound
  47. return workFound;
  48. }

computeDatanodeWork()方法的处理逻辑大体如下:

1、如果namesystem处于安全模式,直接返回0;

2、通过心跳管理器heartbeatManager获取存活数据节点数numlive;

3、计算每个周期集群需要复制的数据块数量blocksToProcess:存活数据节点数numlive乘以集群每个周期每个DataNode平均待复制的数据块数量blocksReplWorkMultiplier,blocksReplWorkMultiplier取参数dfs.namenode.replication.work.multiplier.per.iteration,参数未配置的话默认为2;

4、计算集群每个周期待删除的无效数据块数量nodesToProcess:存活数据节点数numlive乘以集群每个周期每个DataNode平均待删除的无效数据块百分比blocksInvalidateWorkPct,blocksInvalidateWorkPct取参数dfs.namenode.invalidate.work.pct.per.iteration,参数未配置的话默认为0.32f,计算结果向上取整;

5、调用computeReplicationWork()方法,传入blocksToProcess,计算复制工作量workFound;

6、namesystem加写锁;

7、调用updateState()方法更新相关状态;

8、将计算得到的复制工作量workFound赋值给被调度复制的数据块数scheduledReplicationBlocksCount;

9、namesystem释放写锁;

10、调用computeInvalidateWork()方法,传入nodesToProcess(),计算删除无效块工作量,并累加到workFound;

11、返回总工作量workFound。

下面,我们看下计算复制工作量的computeReplicationWork()方法,代码如下:

  1. /**
  2. * Scan blocks in {@link #neededReplications} and assign replication
  3. * work to data-nodes they belong to.
  4. *
  5. * The number of process blocks equals either twice the number of live
  6. * data-nodes or the number of under-replicated blocks whichever is less.
  7. *
  8. * @return number of blocks scheduled for replication during this iteration.
  9. */
  10. int computeReplicationWork(int blocksToProcess) {
  11. List<List<Block>> blocksToReplicate = null;
  12. // namesystem加写锁
  13. namesystem.writeLock();
  14. try {
  15. // Choose the blocks to be replicated
  16. // 通过neededReplications的chooseUnderReplicatedBlocks()方法,
  17. // 选取blocksToProcess个待复制的数据块,放入blocksToReplicate列表,
  18. // blocksToReplicate是一个数据块列表的列表,外层的位置索引代表数据块复制的优先级
  19. blocksToReplicate = neededReplications
  20. .chooseUnderReplicatedBlocks(blocksToProcess);
  21. } finally {
  22. // namesystem释放写锁
  23. namesystem.writeUnlock();
  24. }
  25. // 调用computeReplicationWorkForBlocks()方法,进行实际数据块复制操作,传入待复制数据块列表的列表,位置索引代表复制的优先级
  26. return computeReplicationWorkForBlocks(blocksToReplicate);
  27. }

computeReplicationWork()方法比较短,逻辑也很清晰,如下:

1、namesystem加写锁;

2、通过neededReplications的chooseUnderReplicatedBlocks()方法,选取blocksToProcess个待复制的数据块,放入blocksToReplicate列表,blocksToReplicate是一个数据块列表的列表,外层的位置索引代表数据块复制的优先级:

关于如何通过neededReplications的chooseUnderReplicatedBlocks()方法选取blocksToProcess个待复制的数据块,请参考《HDFS源码分析之UnderReplicatedBlocks(二)》一文;

3、namesystem释放写锁;

4、调用computeReplicationWorkForBlocks()方法,进行实际数据块复制操作,传入待复制数据块列表的列表,位置索引代表复制的优先级。

HDFS源码分析数据块复制监控线程ReplicationMonitor(一)的更多相关文章

  1. HDFS源码分析数据块复制监控线程ReplicationMonitor(二)

    HDFS源码分析数据块复制监控线程ReplicationMonitor(二)

  2. HDFS源码分析数据块复制之PendingReplicationBlocks

    PendingReplicationBlocks实现了所有正在复制的数据块的记账工作.它实现以下三个主要功能: 1.记录此时正在复制的块: 2.一种对复制请求进行跟踪的粗粒度计时器: 3.一个定期识别 ...

  3. HDFS源码分析数据块复制选取复制源节点

    数据块的复制当然需要一个源数据节点,从其上拷贝数据块至目标数据节点.那么数据块复制是如何选取复制源节点的呢?本文我们将针对这一问题进行研究. 在BlockManager中,chooseSourceDa ...

  4. HDFS源码分析数据块校验之DataBlockScanner

    DataBlockScanner是运行在数据节点DataNode上的一个后台线程.它为所有的块池管理块扫描.针对每个块池,一个BlockPoolSliceScanner对象将会被创建,其运行在一个单独 ...

  5. HDFS源码分析数据块汇报之损坏数据块检测checkReplicaCorrupt()

    无论是第一次,还是之后的每次数据块汇报,名字名字节点都会对汇报上来的数据块进行检测,看看其是否为损坏的数据块.那么,损坏数据块是如何被检测的呢?本文,我们将研究下损坏数据块检测的checkReplic ...

  6. HDFS源码分析数据块之CorruptReplicasMap

    CorruptReplicasMap用于存储文件系统中所有损坏数据块的信息.仅当它的所有副本损坏时一个数据块才被认定为损坏.当汇报数据块的副本时,我们隐藏所有损坏副本.一旦一个数据块被发现完好副本达到 ...

  7. HDFS源码分析之数据块及副本状态BlockUCState、ReplicaState

    关于数据块.副本的介绍,请参考文章<HDFS源码分析之数据块Block.副本Replica>. 一.数据块状态BlockUCState 数据块状态用枚举类BlockUCState来表示,代 ...

  8. HDFS源码分析心跳汇报之数据块汇报

    在<HDFS源码分析心跳汇报之数据块增量汇报>一文中,我们详细介绍了数据块增量汇报的内容,了解到它是时间间隔更长的正常数据块汇报周期内一个smaller的数据块汇报,它负责将DataNod ...

  9. HDFS源码分析心跳汇报之数据块增量汇报

    在<HDFS源码分析心跳汇报之BPServiceActor工作线程运行流程>一文中,我们详细了解了数据节点DataNode周期性发送心跳给名字节点NameNode的BPServiceAct ...

随机推荐

  1. 洛谷P2168 荷马史诗

    哈夫曼树原理. k=2时,和合并果子一样一样的. 由此思考,k>2时,应该也有相似的原理.确实如此,k进制哈夫曼树,每个结点最多会有k-1个子结点,对应k-1个元素(“元素”可以是更深层的子树) ...

  2. *LOJ#2134. 「NOI2015」小园丁与老司机

    $n \leq 5e4$个平面上的点,从原点出发,能从当前点向左.右.上.左上或右上到达该方向最近的给定点.问三个问:一.最多经过多少点:二.前一问的方案:三.其所有方案种非左右走的边至少要开几辆挖掘 ...

  3. [LeetCode] Path Sum II 深度搜索

    Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given su ...

  4. C#使用DirectoryEntry类操作Windows帐户

    1.创建windows帐户 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 /// <summary> /// 创建Windows帐户 /// </summa ...

  5. hdu 2521 反素数(打表)

    反素数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  6. extern "C"解析

    转自大牛的解析(非常具体详细)http://www.cnblogs.com/skynet/archive/2010/07/10/1774964.html 我做个简单的标注方便以后自己查看: 在用C++ ...

  7. Excel Sheet Column Title - LeetCode

    Given a positive integer, return its corresponding column title as appear in an Excel sheet. For exa ...

  8. Mac. 文件夹赋予权限

    1. click on your background to go to finder click on go and go to folder /usr right click on local a ...

  9. selenium用法 (python)

    滑动到指定元素位置 browser.find_element_by_xpath("//font[text()='资产管理部经办人'][1]").location_once_scro ...

  10. ASP.NET Web API是如何根据请求选择Action的?[下篇] 【转】

    再<上篇>中我们简单介绍了用于实现Action选择机制的HttpActionSelector,接下来我们来讨论本章最为核心的内 容:ASP.NET Web API如何利用HttpActio ...