【前言】
在dn整体架构一文中提到了逻辑业务层包括BP管理、块扫描和目录扫描,文本就来聊聊块扫描和目录扫描的大概原理。
【块扫描】
块扫描主要是对dn上存储的所有block进行数据完整性校验。进一步来讲,就是读取dn存储的所有block文件,以及对应的元数据(meta)文件,然后进行数据完整性的校验。
在dn的具体实现中,块扫描对应的类BlockScanner只是一个壳,具体扫描由VolumeScanner负责。每个VolumeScanner负责一个目录,同时也是一个独立的线程。在该线程中,扫描并读取各自目录中的block数据。
每个配置的目录都有一个唯一的ID,BlockScanner中就以该ID为key,VolumeScanner为value,保存所有的VolumeScanner。
由于扫描需要读取具体block文件中的数据和meta文件中的数据,为了避免扫描产生的IO对正常读写IO性能产生影响,因此,块扫描会进行一定的限速处理。
又因为有了限速,一次完整的块扫描耗时是非常长的,为了避免扫描过程中,dn意外的重启,导致重新开始扫描,因此扫描过程中会定期将扫描的信息记录到磁盘文件中(游标文件),dn重启后读取该文件继续本次扫描直到扫描完所有的block。
另外,VolumeScanner并不是在dn启动后就创建运行的,而是当dn成功向nn获取到命名空间信息后,才会在每个VolumeScanner中添加对应的BP,并启动扫描。也就是说只有获取到命名空间(包括BP信息)的BP,才会扫描对应目录下的block,而未被添加的BP,则不会扫描。
相关的配置:
【目录扫描】
目录扫描的主要目的判断是磁盘中实际存储的block文件和内存中记录的是否一致。具体包括检查block是否存在,block的大小、时间戳等和内存中记录的是否一致。如果有不一致的情况,会以实际磁盘中的文件为准,修正内存中记录的信息。
与块扫描不同,目录扫描不会进行实际文件的读取,仅仅是扫描目录下的文件,从文件名去判断内存中是否存在对应的block。
相关的配置:
有几点需要注意:
【总结】
dn的块扫描和目录扫描一定程度上保证了数据的完整性。