文档首页 > > 开发指南> HDFS应用开发> 开发规范> 规则

规则

分享
更新时间: 2019/04/30 GMT+08:00

HDFS NameNode元数据存储路径

NameNode元数据信息的默认存储路径为“${BIGDATA_DATA_HOME}/namenode/data”,该参数用于确定HDFS文件系统的元数据信息的保存路径。

HDFS需要开启NameNode镜像备份

NameNode的镜像备份参数为“fs.namenode.image.backup.enable”,需要设置该值为“true”,系统即可定期备份NameNode的数据。

HDFS需要开启DataNode数据存储路径

DataNode默认存储路径配置为:${BIGDATA_DATA_HOME}/hadoop/dataN/dn/datadir(N≥1),N为数据存放的目录个数。

例如:${BIGDATA_DATA_HOME}/hadoop/data1/dn/datadir、${BIGDATA_DATA_HOME}/hadoop/data2/dn/datadir

设置后,数据会存储到节点上每个挂载磁盘的对应目录下面。

HDFS提高读取写入性能方式

写入数据流程:HDFS Client收到业务数据后,从NameNode获取到数据块编号、位置信息后,联系DataNode,并将需要写入数据的DataNode建立起流水线,完成后,客户端再通过自有协议写入数据到Datanode1,再有DataNode1复制到DataNode2、DataNode3(三备份)。写完的数据,将返回确认信息给HDFS Client。

  1. 合理设置块大小,如设置dfs.blocksize为 268435456(即256MB)。
  2. 对于一些不可能重用的大数据,缓存在操作系统的缓存区是无用的。可将以下两参数设置为false。

    dfs.datanode.drop.cache.behind.reads和dfs.datanode.drop.cache.behind.writes

MapReduce中间文件存放路径

MapReduce默认中间文件夹存放路径只有一个,${hadoop.tmp.dir}/mapred/local,建议修改为每个磁盘下均可存放中间文件。

例如:/hadoop/hdfs/data1/mapred/local、/hadoop/hdfs/data2/mapred/local、/hadoop/hdfs/data3/mapred/local等,不存在的目录会自动忽略。

JAVA开发时,申请资源须在finally释放

申请的HDFS资源需要在try/finally中释放,而不能只在try语句之外释放,否则会导致异常情况下的资源泄漏。

HDFS文件操作API概述

Hadoop中关于文件操作类基本上全部是在"org.apache.hadoop.fs"包中,这些API能够支持的操作包含:打开文件,读写文件,删除文件等。Hadoop类库中最终面向用户提供的接口类是FileSystem,该类是个抽象类,只能通过来类的get方法得到具体类。get方法存在几个重载版本,常用的是这个:

static FileSystem get(Configuration conf);

该类封装了几乎所有的文件操作,例如mkdir,delete等。综上基本可以得出操作文件的程序库框架:

operator()
{
    得到Configuration对象
    得到FileSystem对象
    进行文件操作
}

HDFS初始化方法

HDFS初始化是指在使用HDFS提供的API之前,需要做的必要工作。

大致过程为:加载HDFS服务配置文件,并进行Kerberos安全认证,认证通过后再实例化Filesystem,之后使用HDFS的API。此处Kerberos安全认证需要使用到的keytab文件,请提前准备,可参考准备开发用户

正确示例:

private  void init() throws IOException {
Configuration conf = new Configuration();
// 读取配置文件 
conf.addResource("user-hdfs.xml");
// 安全模式下,先进行安全认证 
if ("kerberos".equalsIgnoreCase(conf.get("hadoop.security.authentication"))) {
String PRINCIPAL = "username.client.kerberos.principal";
String KEYTAB = "username.client.keytab.file";
// 设置keytab密钥文件 
conf.set(KEYTAB, System.getProperty("user.dir") + File.separator + "conf"
?????+ File.separator + conf.get(KEYTAB));

// 设置kerberos配置文件路径 */
String krbfilepath = System.getProperty("user.dir") + File.separator + "conf"
?????+ File.separator + "krb5.conf";
System.setProperty("java.security.krb5.conf", krbfilepath);
// 进行登录认证 */
SecurityUtil.login(conf, KEYTAB, PRINCIPAL);
}

// 实例化文件系统对象
fSystem = FileSystem.get(conf);
}

HDFS上传本地文件

通过FileSystem.copyFromLocalFile(Path src,Patch dst)可将本地文件上传到HDFS的制定位置上,其中src和dst均为文件的完整路径。

正确示例:

public class CopyFile {
        public static void main(String[] args) throws Exception {
         Configuration conf=new Configuration();
         FileSystem hdfs=FileSystem.get(conf);
               //本地文件
        Path src =new Path("D:\\HebutWinOS");
        //HDFS为止
         Path dst =new Path("/");
               hdfs.copyFromLocalFile(src, dst);
         System.out.println("Upload to"+conf.get("fs.default.name"));
             FileStatus files[]=hdfs.listStatus(dst);
             for(FileStatus file:files){
                 System.out.println(file.getPath());
             }
        }
}

HDFS创建目录

通过"FileSystem.mkdirs(Path f)"可在HDFS上创建目录,其中f为目录的完整路径。

正确示例:

public class CreateDir {
    public static void main(String[] args) throws Exception{
        Configuration conf=new Configuration();
        FileSystem hdfs=FileSystem.get(conf);
               Path dfs=new Path("/TestDir");
               hdfs.mkdirs(dfs);
    }
}

查看HDFS文件的最后修改时间

通过FileSystem.getModificationTime()可查看指定HDFS文件的修改时间。

正确示例:

     public static void main(String[] args) throws Exception {
         Configuration conf=new Configuration();
         FileSystem hdfs=FileSystem.get(conf);
         Path fpath =new Path("/user/hadoop/test/file1.txt");
         FileStatus fileStatus=hdfs.getFileStatus(fpath);
         long modiTime=fileStatus.getModificationTime();
         System.out.println("file1.txt的修改时间是"+modiTime); }

读取HDFS某个目录下的所有文件

通过FileStatus.getPath( )可查看指定HDFS中某个目录下所有文件。

正确示例:

public static void main(String[] args) throws Exception {
        Configuration conf=new Configuration();
        FileSystem hdfs=FileSystem.get(conf);

        Path listf =new Path("/user/hadoop/test");

        FileStatus stats[]=hdfs.listStatus(listf);
        for(int i = 0; i < stats.length; ++i)                                                                            {
       System.out.println(stats[i].getPath().toString())
       }
        hdfs.close();
    }

查找某个文件在HDFS集群的位置

通过FileSystem.getFileBlockLocation(FileStatus file,long start,long len)可查找指定文件在HDFS集群上的位置,其中file为文件的完整路径,start和len来标识查找文件的路径。

正确示例:

public static void main(String[] args) throws Exception {
        Configuration conf=new Configuration();
        FileSystem hdfs=FileSystem.get(conf);
        Path fpath=new Path("/user/hadoop/cygwin");

        FileStatus filestatus = hdfs.getFileStatus(fpath);
        BlockLocation[] blkLocations = hdfs.getFileBlockLocations(filestatus, 0, filestatus.getLen());

        int blockLen = blkLocations.length;
        for(int i=0;i < blockLen;i++){
        String[] hosts = blkLocations[i].getHosts();
        System.out.println("block_"+i+"_location:"+hosts[0]);
        }
    }

获取HDFS集群上所有节点名称信息

通过DatanodeInfo.getHostName( )可获取HDFS集群上的所有节点名称。

正确示例:

public static void main(String[] args) throws Exception {
        Configuration conf=new Configuration();
        FileSystem fs=FileSystem.get(conf);
       
        DistributedFileSystem hdfs = (DistributedFileSystem)fs;
        DatanodeInfo[] dataNodeStats = hdfs.getDataNodeStats();
       
        for(int i=0;i < dataNodeStats.length;i++){
            System.out.println("DataNode_"+i+"_Name:"+dataNodeStats[i].getHostName());
        }
    }

多线程安全登录方式

如果有多线程进行login的操作,当应用程序第一次登录成功后,所有线程再次登录时应该使用relogin的方式。

login的代码样例:

  private Boolean login(Configuration conf){
    boolean flag = false;
    UserGroupInformation.setConfiguration(conf);
    
    try {
      UserGroupInformation.loginUserFromKeytab(conf.get(PRINCIPAL), conf.get(KEYTAB));
      System.out.println("UserGroupInformation.isLoginKeytabBased(): " +UserGroupInformation.isLoginKeytabBased());
      flag = true;
    } catch (IOException e) {
      e.printStackTrace();
    }
    return flag;
    
  }

relogin的代码样例:

public Boolean relogin(){
        boolean flag = false;
        try {
            
          UserGroupInformation.getLoginUser().reloginFromKeytab();
          System.out.println("UserGroupInformation.isLoginKeytabBased(): " +UserGroupInformation.isLoginKeytabBased());
          flag = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return flag;
    }
分享:

    相关文档

    相关产品

文档是否有解决您的问题?

提交成功!

非常感谢您的反馈,我们会继续努力做到更好!

反馈提交失败,请稍后再试!

*必选

请至少选择或填写一项反馈信息

字符长度不能超过200

提交反馈 取消

如您有其它疑问,您也可以通过华为云社区问答频道来与我们联系探讨

智能客服提问云社区提问