HDFS磁盘文件
HDFS数据文件落地磁盘后,会有如下的文件列表;一个数据块,一个是数据的校验文件。
相同文件的同一个block,在不同节点的副本中;block名字和校验文件都相同,可以相互校验。
集群启动过程中,DataNode会校验自己的文件,并上报校验结果到NameNode。
blk_1074062502
blk_1074062502_321678.meta
blk_1074062503
blk_1074062503_321679.meta
blk_1074062504
blk_1074062504_321680.meta
校验示例代码
/**
* 文件块校验
* @param metaPath 校验文件路径
* @param blkPath Block数据文件
* @return 校验通过true,否则false。
* @throws IOException
*/
public static boolean hdfsBlockCheck(String metaPath, String blkPath)
throws IOException {
// 元数据解析
DataInputStream input= new DataInputStream(new FileInputStream(metaPath));
BlockMetadataHeader readHeader = BlockMetadataHeader.readHeader(input);
// 元数据版本号
// short version = readHeader.getVersion();
DataChecksum checksum = readHeader.getChecksum();
// 512 每多少数据做一次校验
int bytesPerChecksum = checksum.getBytesPerChecksum();
// CRC32C : CRC即循环冗余校验码
Type checksumType = checksum.getChecksumType();
// 校验过程
DataChecksum dataChecksum = DataChecksum.newDataChecksum(checksumType, bytesPerChecksum);
// 读取数据块,启动校验过程
byte[] dataBytes = new byte[bytesPerChecksum];
byte[] checkBytes = new byte[dataChecksum.getChecksumSize()];
DataInputStream dataIn = new DataInputStream(new FileInputStream(blkPath));
// 文件长度
long length = new File(blkPath).length();
boolean result = true;
while(dataIn.read(dataBytes) > 0) {
// 记录剩余文件长度
length = length - bytesPerChecksum;
input.read(checkBytes);
dataChecksum.reset();
// 如果length小于0,那么最后一部分数据校验长度,不满bytesPerChecksum
if(length >= 0) {
dataChecksum.update(dataBytes, 0, dataBytes.length);
} else {
dataChecksum.update(dataBytes, 0, (int)(length + bytesPerChecksum));
}
// 校验失败,直接返回
if(!dataChecksum.compare(checkBytes, 0)) {
result = false;
break;
}
}
// 关闭数据流
input.close();
dataIn.close();
return result;
}
测试示例代码:
// 元数据及其校验的数据块
String blk_meta = "C:\\Users\\TMS1000\\Downloads\\blk_1074062502_321678.meta";
String blk_path = "C:\\Users\\TMS1000\\Downloads\\38\\blk_1074062502";
// 元数据解析
boolean hdfsBlockCheck = hdfsBlockCheck(blk_meta, blk_path);
System.err.println(hdfsBlockCheck);