说明
周期性的验证Datanode上所有存储块的正确性,损坏的报告给Namenode。
DataBlockScanner持有多个BlockPoolSliceScanner的引用。
3.0之后代码实现发生了大的改动,BlockScanner,引用VolumeScanner.在dn和sender时,指定一些优先扫描的嫌疑block,优先扫描。
DataBlockScanner实现
数据块扫描是通过BlockPoolSliceScanner实现的。
DataBlockScanner是一个线程类
数据结构
blockPoolSliceMap维护BlockPoolSliceScanner对象
Run
选择blockPoolSliceMap中最久未访问的BlockPoolSliceScanner对象
调用scanBlockPoolSlice()扫描数据块
run结束时,关闭所有的BlockPoolSliceScanner对象,清理工作。
addBlock
添加或者删除块时,最后调用datanode.closeBlock()
这时需要调用DataBlockScanner.addBlock()
scan
调用blockPoolSliceScanner.scanBlockPoolSlice扫描数据块
BlockPoolSliceScanner实现
blockpoolSliceScanner实际进行一个blockpool的所有数据块扫描
这里猜测有有优先级的,某些块先扫描。
数据结构
BlockScanInfo 保留数据块扫描信息,可以比较。
scan
DataBlockScanner.blockInfoSet中获取一个数据块,进行校验,验证完成之后进行保存。
如果发现异常了,最终调用datanode.hanldeBadBlock进行汇报。
DirectoryScanner
定期扫描磁盘上的数据块,检查是否和FsDatasetImpl中描述一致。
数据结构
1)收集磁盘数据块线程池
reportCompileThreadPool
2)diffs
保存不一致的内存结构,结束之后更新到FsDatasetImpl上
3) 主线程
定期调用run,进行整体扫描
run
- 如何收集磁盘信息
独立线程,FSVolumeImpl扫描文件。找到文件下面的目录。同时从文件信息中找到block信息。 - 如何收集内存中数据块信息
FsDatasetImpl获取的 - 比较哪些信息?
blockId是否missing
metastore存在,但是文件丢失等
长度不匹配
小结
代码不一致,但是整体思路差不多
BlockScanner保存多个VolumeScanner进行具体的扫描
BlockScanner维护需要扫描的块,在datanode closeblock时,会把一些块加入到待扫描的块
BlockScannerInfo继承自Block,保存扫描信息,可以排序。
DirectorySanncer整体扫描内存和磁盘的区别