【问题标题】:HDFS File ChecksumHDFS 文件校验和
【发布时间】:2013-01-28 13:36:16
【问题描述】:

我试图在使用 Hadoop API - DFSCleint.getFileChecksum() 复制到 HDFS 后检查文件的一致性。

我得到上述代码的以下输出:

Null
HDFS : null
Local : null

谁能指出错误或错误? 这是代码:

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileChecksum;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.LocalFileSystem;
import org.apache.hadoop.fs.Path;


public class fileCheckSum {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub

        Configuration conf = new Configuration();

         FileSystem hadoopFS = FileSystem.get(conf);
    //  Path hdfsPath = new Path("/derby.log");

        LocalFileSystem localFS = LocalFileSystem.getLocal(conf);
    //      Path localPath = new Path("file:///home/ubuntu/derby.log");


    //  System.out.println("HDFS PATH : "+hdfsPath.getName());
    //      System.out.println("Local PATH : "+localPath.getName());

        FileChecksum hdfsChecksum = hadoopFS.getFileChecksum(new Path("/derby.log"));
        FileChecksum localChecksum = localFS.getFileChecksum(new Path("file:///home/ubuntu/derby.log"));


        if(null!=hdfsChecksum || null!=localChecksum){
            System.out.println("HDFS Checksum : "+hdfsChecksum.toString()+"\t"+hdfsChecksum.getLength());
            System.out.println("Local Checksum : "+localChecksum.toString()+"\t"+localChecksum.getLength());

            if(hdfsChecksum.toString().equals(localChecksum.toString())){
                System.out.println("Equal");
            }else{
                System.out.println("UnEqual");

            }
        }else{
            System.out.println("Null");
            System.out.println("HDFS : "+hdfsChecksum);
            System.out.println("Local : "+localChecksum);

        }

    }

}

【问题讨论】:

  • 为什么HDFS文件的校验和为NULL?
  • 还有其他方法可以计算 HDFS 上文件的 MD5 校验和(我使用的是 hadoop 0.20,CDH3u3)。另外,任何人都可以为 CDH4.1 (MRv1) 建议相同的功能。

标签: java hadoop mapreduce hdfs checksum


【解决方案1】:

由于您没有在conf 上设置远程地址并且基本上使用相同的配置,因此hadoopFSlocalFS 都指向LocalFileSystem 的实例。

getFileChecksum 未针对 LocalFileSystem 实现并返回 null。不过,它应该适用于DistributedFileSystem,如果您的conf 指向分布式集群,FileSystem.get(conf) 应该返回一个DistributedFileSystem 的实例,该实例返回一个MD5 of MD5 of CRC32 checksums 大小为bytes.per.checksum 的块。该值取决于块大小和集群范围的配置bytes.per.checksum。这就是为什么这两个参数也被编码在分布式校验和的返回值中作为算法的名称:MD5-of-xxxMD5-of-yyyCRC32 其中xxx是每个块的CRC校验和数量,yyy是bytes.per.checksum参数。

getFileChecksum 并非旨在跨文件系统进行比较。虽然可以在本地模拟分布式校验和,或者手工制作 map-reduce 作业来计算本地哈希的等价物,但我建议依靠 Hadoop 自己的完整性检查,当文件被写入或从 Hadoop 读取时发生

【讨论】:

  • 感谢您的回复。我在调试时明白了这一点。我看到我的配置对象没有读取 hadoop conf 文件。现在我正在显式添加 conf 文件并计算来自 unix shell 的本地文件的 md5sum 和来自 java 程序的 hdfs 的 md5。但是对于同一个文件,这两个值是不同的。
  • 我将我的 conf 文件添加为 conf.addResource(new Path("/home/ubuntu/CDH3/hadoop-0.20.2-cdh3u3/conf/core-site.xml")); conf.addResource(new Path("/home/ubuntu/CDH3/hadoop-0.20.2-cdh3u3/conf/hdfs-site.xml"));
  • DFSClient.getFileChecksum 是否与我使用的不同?如果是,那么我该如何使用此方法。我查看了 hadoop src,发现此方法已重载,但我无法将其与一个参数(String src)一起使用。
  • 文件的CRC32的MD5的MD5。在这里实现:github.com/apache/hadoop/blob/trunk/src/hdfs/org/apache/hadoop/…
  • ClientProtocol namenode, SocketFactory socketFactory, int socketTimeout 的值可能是多少。此方法返回与 unix shell 返回相同的值,返回 "md5sum "???
【解决方案2】:

试试这个。在此我计算了本地和 HDFS 文件的 MD5,然后比较了两个文件的相等性。希望这会有所帮助。

public static void compareChecksumForLocalAndHdfsFile(String sourceHdfsFilePath, String sourceLocalFilepath, Map<String, String> hdfsConfigMap)
        throws Exception {
    System.setProperty("HADOOP_USER_NAME", hdfsConfigMap.get(Constants.USERNAME));
    System.setProperty("hadoop.home.dir", "/tmp");
    Configuration hdfsConfig = new Configuration();
    hdfsConfig.set(Constants.USERNAME, hdfsConfigMap.get(Constants.USERNAME));
    hdfsConfig.set("fsURI", hdfsConfigMap.get("fsURI"));
    FileSystem hdfs = FileSystem.get(new URI(hdfsConfigMap.get("fsURI")), hdfsConfig);
    Path inputPath = new Path(hdfsConfigMap.get("fsURI") + "/" + sourceHdfsFilePath);
    InputStream is = hdfs.open(inputPath);
    String localChecksum = getMD5Checksum(new FileInputStream(sourceLocalFilepath));
    String hdfsChecksum = getMD5Checksum(is);
    if (null != hdfsChecksum || null != localChecksum) {
        System.out.println("HDFS Checksum : " + hdfsChecksum.toString() + "\t" + hdfsChecksum.length());
        System.out.println("Local Checksum : " + localChecksum.toString() + "\t" + localChecksum.length());

        if (hdfsChecksum.toString().equals(localChecksum.toString())) {
            System.out.println("Equal");
        } else {
            System.out.println("UnEqual");
        }
    } else {
        System.out.println("Null");
        System.out.println("HDFS : " + hdfsChecksum);
        System.out.println("Local : " + localChecksum);
    }
}

public static byte[] createChecksum(String filename) throws Exception {
    InputStream fis = new FileInputStream(filename);

    byte[] buffer = new byte[1024];
    MessageDigest complete = MessageDigest.getInstance("MD5");
    int numRead;

    do {
        numRead = fis.read(buffer);
        if (numRead > 0) {
            complete.update(buffer, 0, numRead);
        }
    } while (numRead != -1);

    fis.close();
    return complete.digest();
}

// see this How-to for a faster way to convert
// a byte array to a HEX string
public static String getMD5Checksum(String filename) throws Exception {
    byte[] b = createChecksum(filename);
    String result = "";

    for (int i = 0; i < b.length; i++) {
        result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
    }
    return result;
}

输出:

HDFS Checksum : d99513cc4f1d9c51679a125702bd27b0    32
Local Checksum : d99513cc4f1d9c51679a125702bd27b0   32
Equal

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-11
    • 2014-03-01
    • 1970-01-01
    • 2020-07-02
    • 2017-07-01
    • 2013-05-23
    相关资源
    最近更新 更多