HDFS源码分析数据块汇报之损坏数据块检测checkReplicaCorrupt()
无论是第一次,还是之后的每次数据块汇报,名字名字节点都会对汇报上来的数据块进行检测,看看其是否为损坏的数据块。那么,损坏数据块是如何被检测的呢?本文,我们将研究下损坏数据块检测的checkReplicaCorrupt()方法。
关于数据块及其副本的状态,请阅读《HDFS源码分析之数据块及副本状态BlockUCState、ReplicaState》一文。
checkReplicaCorrupt()方法专门用于损坏数据块检测,代码如下:
- /**
- * The next two methods test the various cases under which we must conclude
- * the replica is corrupt, or under construction. These are laid out
- * as switch statements, on the theory that it is easier to understand
- * the combinatorics of reportedState and ucState that way. It should be
- * at least as efficient as boolean expressions.
- *
- * @return a BlockToMarkCorrupt object, or null if the replica is not corrupt
- */
- private BlockToMarkCorrupt checkReplicaCorrupt(
- Block reported, ReplicaState reportedState,
- BlockInfo storedBlock, BlockUCState ucState,
- DatanodeDescriptor dn) {
- // 检测数据节点DataNode上的数据块副本状态ReplicaState实例reportedState
- switch(reportedState) {
- case FINALIZED:// 数据块副本如果为FINALIZED状态,即没有被修改的状态
- // 需要再看名字节点数据块状态BlockUCState,即ucState
- switch(ucState) {
- case COMPLETE:// 如果是COMPLETE状态,不应被汇报为坏块:这种情况下,数据节点副本已经处于不会被修改的FINALIZED状态,
- // 而名字节点中的数据块状态为COMPLETE,也是不会被修改的状态,
- // 并且其他数据节点已经汇报过该数据块对应的一个副本,所以不会是损坏的数据块
- case COMMITTED:// 如果是COMMITTED状态,虽然数据块不会被修改,但是还没有任何数据节点汇报过副本,还需要做以下时间戳和大小的判断:
- if (storedBlock.getGenerationStamp() != reported.getGenerationStamp()) {
- // 如果存储的数据块时间戳不等于汇报的数据块时间戳,需要汇报为坏块,
- // 且损坏原因为Reason.GENSTAMP_MISMATCH,即时间戳不匹配
- final long reportedGS = reported.getGenerationStamp();
- return new BlockToMarkCorrupt(storedBlock, reportedGS,
- "block is " + ucState + " and reported genstamp " + reportedGS
- + " does not match genstamp in block map "
- + storedBlock.getGenerationStamp(), Reason.GENSTAMP_MISMATCH);
- } else if (storedBlock.getNumBytes() != reported.getNumBytes()) {
- // 如果存储的数据块大小不等于汇报的数据块大小,需要汇报为坏块
- // 且损坏原因为Reason.SIZE_MISMATCH,即大小不匹配
- return new BlockToMarkCorrupt(storedBlock,
- "block is " + ucState + " and reported length " +
- reported.getNumBytes() + " does not match " +
- "length in block map " + storedBlock.getNumBytes(),
- Reason.SIZE_MISMATCH);
- } else {
- // 其它情况下不是一个坏块
- return null; // not corrupt
- }
- case UNDER_CONSTRUCTION:// 如果是UNDER_CONSTRUCTION状态,数据还在被写入,所以需要做以下时间戳的判断:
- if (storedBlock.getGenerationStamp() > reported.getGenerationStamp()) {
- // 如果存储的数据块时间戳不等于汇报的数据块时间戳,需要汇报为坏块,
- // 且损坏原因为Reason.GENSTAMP_MISMATCH,即时间戳不匹配
- final long reportedGS = reported.getGenerationStamp();
- return new BlockToMarkCorrupt(storedBlock, reportedGS, "block is "
- + ucState + " and reported state " + reportedState
- + ", But reported genstamp " + reportedGS
- + " does not match genstamp in block map "
- + storedBlock.getGenerationStamp(), Reason.GENSTAMP_MISMATCH);
- }
- return null;
- default:
- // 其他情况下均不是损坏的数据块
- return null;
- }
- case RBW:// 数据块副本为正在被写入状态,不应被汇报为坏块
- case RWR:// 数据块副本为正等待被恢复状态
- if (!storedBlock.isComplete()) {
- // 如果存储的数据块不是Complete状态,则不是一个坏块
- return null; // not corrupt
- } else if (storedBlock.getGenerationStamp() != reported.getGenerationStamp()) {
- // 否则需要判断时间戳是否一致
- final long reportedGS = reported.getGenerationStamp();
- return new BlockToMarkCorrupt(storedBlock, reportedGS,
- "reported " + reportedState + " replica with genstamp " + reportedGS
- + " does not match COMPLETE block's genstamp in block map "
- + storedBlock.getGenerationStamp(), Reason.GENSTAMP_MISMATCH);
- } else { // COMPLETE block, same genstamp
- if (reportedState == ReplicaState.RBW) {
- // 如果数据块副本为正在写入状态RBW,不会是一个损坏的数据块
- // If it's a RBW report for a COMPLETE block, it may just be that
- // the block report got a little bit delayed after the pipeline
- // closed. So, ignore this report, assuming we will get a
- // FINALIZED replica later. See HDFS-2791
- LOG.info("Received an RBW replica for " + storedBlock +
- " on " + dn + ": ignoring it, since it is " +
- "complete with the same genstamp");
- return null;
- } else {
- // 否则为一个损坏的数据块,且损坏原因为Reason.INVALID_STATE
- return new BlockToMarkCorrupt(storedBlock,
- "reported replica has invalid state " + reportedState,
- Reason.INVALID_STATE);
- }
- }
- case RUR: // should not be reported 副本处于恢复状态下,不应被汇报为坏块
- case TEMPORARY: // should not be reported 副本为仅为复制而创建的临时副本,不应被汇报为坏块
- default:
- String msg = "Unexpected replica state " + reportedState
- + " for block: " + storedBlock +
- " on " + dn + " size " + storedBlock.getNumBytes();
- // log here at WARN level since this is really a broken HDFS invariant
- LOG.warn(msg);
- return new BlockToMarkCorrupt(storedBlock, msg, Reason.INVALID_STATE);
- }
- }
checkReplicaCorrupt()方法处理逻辑略显复杂,但是还算清晰,它需要被汇报的数据块Block实例reported、副本状态实例ReplicaState、数据块状态BlockUCState等参数,主要处理逻辑如下:
基于数据节点DataNode上的数据块副本状态ReplicaState实例reportedState进行检测,如果:
1、数据块副本状态ReplicaState为正在写入RBW、正在恢复RUR、为复制而创建的临时副本TEMPORARY三种状态,则肯定不是损坏的数据块,因为这些数据块副本还处于不确定的状态,还需要被写入或者被舍弃等;
2、数据块副本状态ReplicaState为FINALIZED的话,说明数据已被完全写入,数据块副本大小及时间戳均不会再发生变化,此时,就等着其所在数据节点DataNode进行数据块汇报,将该数据块副本汇报给名字节点NameNode,那么我们需要看数据块Block在名字节点内的状态:
2.1、如果是COMPLETE状态,不应被汇报为坏块:这种情况下,数据节点副本已经处于不会被修改的FINALIZED状态,而名字节点中的数据块状态为COMPLETE,也是不会被修改的状态,并且其他数据节点已经汇报过该数据块对应的一个副本,所以不会是损坏的数据块;
2.2、如果是COMMITTED状态,虽然数据块不会被修改,但是还没有任何数据节点汇报过副本,还需要做以下时间戳和大小的判断:
2.2.1、如果名字节点存储的数据块时间戳不等于汇报的数据块时间戳,需要汇报为坏块,且损坏原因为Reason.GENSTAMP_MISMATCH,即时间戳不匹配;
2.2.2、如果名字节点存储的数据块大小不等于汇报的数据块大小,需要汇报为坏块,且损坏原因为Reason.SIZE_MISMATCH,即大小不匹配;
2.2.3、其它情况下不是一个坏块;
2.3、如果是UNDER_CONSTRUCTION状态,数据还在被写入,所以可以忽略大小,只做以下时间戳的判断:
2.3.1、如果名字节点存储的数据块时间戳不等于汇报的数据块时间戳,需要汇报为坏块,且损坏原因为Reason.GENSTAMP_MISMATCH,即时间戳不匹配;
2.3.2、其它情况下不是一个坏块;
2.4、其他情况下均不是损坏的数据块;
3、数据块副本为正等待被恢复状态RWR的话,需要看数据块在名字节点NameNode的状态:
3.1、如果名字节点存储的数据块Block不是COMPLETE状态,则不是一个坏块,此时数据块尚未上报过名字节点NameNode;
3.2、如果名字节点存储的数据块是COMPLETE状态,说明之前已经上报过,需要判断时间戳是否一致,如果时间戳不一致的话,则说明其是一个坏块;
3.3、如果名字节点存储的数据块是COMPLETE状态,说明之前已经上报过,且时间戳一致的话,如果数据块副本为正在写入状态RBW,不会是一个损坏的数据块,否则为一个损坏的数据块,且损坏原因为Reason.INVALID_STATE;
4、其他情况下均为一个坏块,且损坏原因为Reason.INVALID_STATE。
BlockToMarkCorrupt是一个数据块标记为坏块的抽象数据结构,它包含四个成员变量,如下:
- /** The corrupted block in a datanode. */
- 数据节点上的坏块数据块信息
- final BlockInfo corrupted;
- /** The corresponding block stored in the BlockManager. */
- // 名字节点BlockManager中存储的相应的数据块信息
- final BlockInfo stored;
- // 损坏原因:字符串类型
- /** The reason to mark corrupt. */
- final String reason;
- // 损坏原因code:枚举类型
- /** The reason code to be stored */
- final Reason reasonCode;
其他的均是构造方法,及覆写的toString()方法,不再赘述!
HDFS源码分析数据块汇报之损坏数据块检测checkReplicaCorrupt()的更多相关文章
- HDFS源码分析心跳汇报之数据块汇报
在<HDFS源码分析心跳汇报之数据块增量汇报>一文中,我们详细介绍了数据块增量汇报的内容,了解到它是时间间隔更长的正常数据块汇报周期内一个smaller的数据块汇报,它负责将DataNod ...
- HDFS源码分析心跳汇报之数据块增量汇报
在<HDFS源码分析心跳汇报之BPServiceActor工作线程运行流程>一文中,我们详细了解了数据节点DataNode周期性发送心跳给名字节点NameNode的BPServiceAct ...
- HDFS源码分析数据块校验之DataBlockScanner
DataBlockScanner是运行在数据节点DataNode上的一个后台线程.它为所有的块池管理块扫描.针对每个块池,一个BlockPoolSliceScanner对象将会被创建,其运行在一个单独 ...
- HDFS源码分析之数据块及副本状态BlockUCState、ReplicaState
关于数据块.副本的介绍,请参考文章<HDFS源码分析之数据块Block.副本Replica>. 一.数据块状态BlockUCState 数据块状态用枚举类BlockUCState来表示,代 ...
- HDFS源码分析数据块复制监控线程ReplicationMonitor(二)
HDFS源码分析数据块复制监控线程ReplicationMonitor(二)
- HDFS源码分析数据块复制监控线程ReplicationMonitor(一)
ReplicationMonitor是HDFS中关于数据块复制的监控线程,它的主要作用就是计算DataNode工作,并将复制请求超时的块重新加入到待调度队列.其定义及作为线程核心的run()方法如下: ...
- HDFS源码分析心跳汇报之数据结构初始化
在<HDFS源码分析心跳汇报之整体结构>一文中,我们详细了解了HDFS中关于心跳的整体结构,知道了BlockPoolManager.BPOfferService和BPServiceActo ...
- HDFS源码分析心跳汇报之周期性心跳
HDFS源码分析心跳汇报之周期性心跳,近期推出!
- HDFS源码分析心跳汇报之DataNode注册
HDFS源码分析心跳汇报之DataNode注册,近期推出!
随机推荐
- 【HDOJ5527】Too Rich(贪心,构造)
题意:给定10种面额的货币和它们的数量上限,问构造出恰好总额为P的最小张数,无解输出-1 T=2e4,p<=1e9,c[i]<=1e5 思路:From https://blog.csdn. ...
- Spring Boot学习——AOP编程的简单实现
首先应该明白一点,AOP是一种编程范式,是一种程序设计思想,与具体的计算机编程语言无关,所以不止是Java,像.Net等其他编程语言也有AOP的实现方式.AOP的思想理念就是将通用逻辑从业务逻辑中分离 ...
- EOJ 3.30 B. 蛇形矩阵【找规律/待补】
[链接]:https://acm.ecnu.edu.cn/contest/59/problem/B/ B. 蛇形矩阵 Time limit per test: 2.0 seconds Memory l ...
- Codeforces Gym 101471D Money for Nothing(2017 ACM-ICPC World Finals D题,决策单调性)
题目链接 2017 ACM-ICPC World Finals Problem D (这题细节真的很多) 把所有的(pi,di)按横坐标升序排序. 对于某个点,若存在一个点在他左下角,那么这个点就是 ...
- 最短Hamilton路径
题目描述 给定一张 n(n≤20) 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径. Hamilton路径的定义是从 0 到 n-1 不重不漏地经过每 ...
- WinSCP介绍、安装、使用(转)
http://blog.csdn.net/liang19890820/article/details/49700931 前言 如果说XManager通过Xshell.Xftp可以很方便的进行远程管理, ...
- ARCGIS 二次开发可以参考的资源(长期更新)
背景: 今天,被领导教导,说是你刚入职,要尽快把项目做起.言语忠恳,而且说不要再在电脑上练习那些小的测试例子了,要直接切入项目,熟悉项目的开发框架,与设计理念.得到,我的负责人(TB)把他做的项目的资 ...
- REMOTE HOST IDENTIFICATION HAS CHANGED 问题解决
今天处理 ssh连接至 ubuntu 服务器时,提示以下错误: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ WARNING ...
- nginx 配置静态目录 访问bootstrap
location /static/ { alias /Users/wangziqiang/djangoprojects/bpmTest/static/; } 注意 /static/ 中 /的完整 ...
- Hadoop之Linux源代码编译
Hadoop开篇,按惯例.先编译源代码.导入到Eclipse.这样以后要了解那块,或者那块出问题了.直接找源代码. 编译hadoop2.4.1源代码之前.必须安装Maven和Ant环境,而且Hadoo ...