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

  • 时间:
  • 浏览:0

        其中等待的图片 初始化的waitForInit()法子比较简单,代码如下:

        首先,可能性blockScanner不为null,直接返回,说明前一天可能性初始化并启动了,但会 ,选泽数据块校验功能无法开启的意味着着reason:

        到了这里,各位看官可能性有个什么的问题,选泽块池所依赖的blockPoolScannerMap集合中的数据是哪里来的呢?答案就在出理 数据节点心跳的BPServiceActor系统进程池中,在完成数据块汇报、出理 来自名字节点NameNode的相关命令等操作后,有如下代码被执行:

               2.5、可能性当前块池对应的心跳服务BPOfferService都有活跃的,不对它进行出理 ,调用removeBlockPool()法子从blockPoolScannerMap中移除数据,并关闭对应BlockPoolSliceScanner,但会 跳过,执行下一轮循环;

               2.2、遍历blockPoolScannerMap集合,取出每个块池ID,即bpid,计算最早的上次浏览时间lastScanTime,和对应块池ID,即nextBpId:

        实际上它是基于DataBlockScanner实例创建有另另一好几个 系统进程池blockScannerThread,将系统进程池blockScannerThread设置为后台系统进程池,但会 启动系统进程池blockScannerThread。

               2.4、可能性nextBpId不为空,没有从blockPoolScannerMap中获取其对应BlockPoolSliceScanner实例返回;

        3、可能性blockPoolScannerMap大小等于0,可能性上述2找没有的话,记录warn日志,No block pool is up, going to wait,但会 等待的图片 5s后继续下一轮循环;

              数据块扫描系统进程池。

        run()法子逻辑比较清晰,大体如下:

        DataBlockScanner系统进程池已创建,并启动,没有大伙儿儿儿儿看下它是如保工作的,接下来看下它的run()法子,代码如下:

        它本质上是等所有块池都被上报至blockPoolScannerMap集合后,才认为已完成初始化,但会 再选泽块池ID,但会 系统进程池休眠5s,继续等待的图片 。代码注释比较删改,这里不再赘述!

       1、TreeMap<String, BlockPoolSliceScanner> blockPoolScannerMap

        既然DataBlockScanner实现了Runnable接口,没有它肯定是作为有另另一好几个 系统进程池在DataNode节点上运行的,大伙儿儿儿儿看下DataNode是如保对其进行构造及启动的,代码如下:

        获取到块池ID,并获取到其对应的块池切片扫描器BlockPoolSliceScanner实例bpScanner了,接下来只是 调用bpScanner的scanBlockPoolSlice()法子,扫描该块池的数据块,并做数据块校验工作了。这方面的内容,请阅读《HDFS源码分析数据块校验之BlockPoolSliceScanner》一文,这里不再做介绍。

        2、当前对象上使用synchronized进行同步,当blockPoolScannerMap大小大于0,即趋于稳定BlockPoolSliceScanner实例时,做以下出理 :

        大伙儿儿儿儿在后面 也提到了可能性当前块池对应的心跳服务BPOfferService都有活跃的,没有会调用removeBlockPool()法子,移除对应的块池,代码如下:

        2、SimulatedFSDataset不支持数据块校验;

        逻辑很简单,首先可可不可以不能看看blockPoolScannerMap集合中是是否是趋于稳定块池blockPoolId,趋于稳定即返回,但会 根据块池blockPoolId、数据节点datanode、存储dataset、配置信息conf等构造BlockPoolSliceScanner实例bpScanner,将块池blockPoolId与bpScanner的映射关系存储到blockPoolScannerMap中,最后记录日志信息。

        DataBlockScanner是运行在数据节点DataNode上的有另另一好几个 后台系统进程池,它负责管理所有块池的数据块扫描工作。当数据节点DataNode发送心跳给名字节点NameNode进行数据块汇报并执行完返回的命令时,会在DataBlockScanner的内部人员集合blockPoolScannerMap中注册块池ID与为此新创建的BlockPoolSliceScanner对象的关系,但会 DataBlockScanner内部人员系统进程池blockScannerThread周期性的选泽块池currentBpId,并获取块池切片扫描器BlockPoolSliceScanner实例bpScanner,继而调用其scanBlockPoolSlice()法子,扫描对应块池里的数据块,进行数据块校验。块池选泽的主要法子只是 优先选泽扫描时间最早的,也只是 自上次扫描以来最长时间没有进行扫描的,按照你这人 法子选泽不成功的话,则默认按照块池ID递增的顺序循环选泽块池。

                         2.1.2、第一次运行时先将firstRun标志设置为false;

               2.3、可能性bpScanner为null,跳过,继续下一轮循环;

        它的主要作用只是 寻找下有另另一好几个 块池ID以进行scan,其趋于稳定有另另一好几个 整体的while循环,循环的条件为可能性所属数据节点DataNode实例datanode正常运行,且当前blockScannerThread系统进程池没有被中断,循环内做以下出理 :

        DataBlockScanner是运行在数据节点DataNode上的有另另一好几个 后台系统进程池。它为所有的块池管理块扫描。针对每个块池,有另另一好几个 BlockPoolSliceScanner对象可能性被创建,其运行在有另另一好几个 单独的系统进程池中,为该块池扫描、校验数据块。当有另另一好几个 BPOfferService服务变成活跃或死亡情况,该类中的blockPoolScannerMap可能性更新。

        首先是由构造函数选泽的有另另一好几个 成员变量:所属数据节点DataNode实例datanode、所属存储FsDatasetSpi实例dataset、配置信息Configuration实例conf,对应构造函数如下:

                         2.1.1、可能性都有第一次运行,系统进程池休眠5s:即firstRun为false,这时可能性趋于稳定InterruptedException异常,中断blockScannerThread系统进程池,但会 跳过,继续下一轮循环;

        可能性数据块校验功能无法开启的原可能性null,构造DataBlockScanner实例,并调用其start()法子启动该系统进程池,但会 在日志文件中记录周期性数据块校验扫描无法启用的意味着着。

               2.4、设置当前块池ID,即currentBpId,从块池切片扫描器BlockPoolSliceScanner实例bpScanner中获取;

        DataBlockScanner系统进程池启动的start()法子如下:

                        2.2.2、可能性t不为0,且可能性块池ID为null,可能性t小于lastScanTime,则将t赋值给lastScanTime,bpid赋值给nextBpId,也只是 计算最早的上次浏览时间lastScanTime,和对应块池ID,即nextBpId;

        2、Thread blockScannerThread

        2、接下来进入有另另一好几个 while循环,循环的条件是可能性所属数据节点DataNode实例datanode正常运行,且当前系统进程池没有被中断:

               2.3、可能性对应块池ID,即nextBpId为null,则取比上次出理 的块池currentBpId高的key作为nextBpId,可能性还没有取出的话,没有取第有另另一好几个 块池ID,作为nextBpId;

        3、退出循环后,遍历blockPoolScannerMap中的每个BlockPoolSliceScanner实例bpss,挨个调用对应shutdown()法子,停止块池切片扫描器BlockPoolSliceScanner。

               2.2、获取下有另另一好几个 块池切片扫描器BlockPoolSliceScanner实例bpScanner,通过调用getNextBPScanner()法子,传入当前块池ID,即currentBpId来实现,首次循环,currentBpId为空,后续会传入前一天出理 的值,下面会对其进行更新;

               2.6、调用块池切片扫描器BlockPoolSliceScanner实例bpScanner的scanBlockPoolSlice()法子,扫描对应块池里的数据块,进行数据块校验;

        大伙儿儿儿儿先看下DataBlockScanner的成员变量,如下:

        1、可能性参数dfs.datanode.scan.period.hours未配置,可能性配置为0,说明数据块校验功能已关闭;

               2.1、出理 第一次运行标志位firstRun:

        代码很简单,不再赘述。

                        2.2.1、根据块池ID,即bpid,取出其对应BlockPoolSliceScanner实例的上次浏览时间t;

        大伙儿儿儿儿接下来看下比较重要的getNextBPScanner()法子,代码如下:

        很简单,数据节点汇报数据块给名字节点,并执行来自名字节点的相关命令后,就可可不可以不能 通过数据节点DataNode中成员变量blockScanner的addBlockPool()法子,再加块池,代码如下:

        总结

        可见,getNextBPScanner()法子优先选泽最早出理 过的块池,找没有的话再按照前一天出理 过的块池ID增长的顺序,找下有另另一好几个 块池ID,按照块池ID大小顺序到尾部的话,再折回取第有另另一好几个 。

               2.1、设定lastScanTime用于记录上次浏览时间,默认值为0;

        但会 设定了有另另一好几个 静态变量,5s的系统进程池休眠周期,即SLEEP_PERIOD_MS,另外有另另一好几个 重要的成员变量是:

        1、首先初始化当前块池ID,即currentBpId,默认为空,再选泽第一次运行标志firstRun,默认当然应该为true;

        1、调用waitForInit()法子等待的图片 初始化;

             存储块池ID到对应BlockPoolScanner实例的映射。当有另另一好几个 BPOfferService服务变成活跃或死亡情况,blockPoolScannerMap可能性随之更新。

        最后,确实找没有就返回null。