ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

HDFS

2022-05-28 10:02:13  阅读:194  来源: 互联网

标签:HDFS 文件 hdfs dfs file NameNode


HDFS

分布式文件系统,Hadoop Distributed File System。HDFS是一种允许文件通过网络再多台主机上共享的文件系统,可以让多台机器上的多个用户分享文件和存储空间。注意:HDFS不适合存储小文件。

HDFS shell

操作格式 hdfs dfs -<hdfs命令> hdfs://ip:port/path,dfs是指操作dfs文件,系统命令中的路径就是在 core-site.xml 中配置的 fs.defaultFS。直接运行 hdfshdfs dfs查看帮助文档。

# 运行命令后没有结果就是成功
hdfs dfs -ls [-R] /       # 查看dfs文件系统的根目录,-R 为递归展示所有
                          # 等同于 hdfs dfs -ls hdfs://ip:port/ ,省略主机名时会通过配置文件获取
hdfs dfs -put file.txt /  # 将文件从os的文件系统上传到dfs的根目录
hdfs dfs -get /file.txt . # 从dfs下载文件到指定目录
hdfs dfs -mkdir [-p] /dir # 创建目录,添加 -p 后可递归创建
hdfs dfs -cat /file.txt   # 查看hdfs根目录下的file.txt文件
hdfs dfs -rm [-r]         # 删除

如何查询hdfs更目录下文件的数量和大小?

hdfs dfs -ls / | grep / | wc -l  # grep用于删除提示信息,保住每行都出现根目录符号
hdfs dfs -ls / | grep / | awk '{print $8, %5}' # 只输出第八行文件名和第五行文件大小

Java 操作 HDFS

package org.example.hdfs;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.URI;

/**
 * java 操作 hdfs
 * 文件操作:上传 下载 删除
 */
public class HdfsOp {
    public static void main(String[] args) throws Exception {
        
        // 获取配置对象
        Configuration conf = new Configuration();
        // conf.set("fs.defaultFS", "hdfs://192.168.56.150:9000");
        
        // 获取操作 HDFS 的对象
        FileSystem fileSystem = FileSystem.get(
                new URI("hdfs://192.168.56.150:9000/"), //指定hdfs的uri,也可在conf中指定
                conf,
                "root" // 指定用户,防止出现权限问题无法上传
        );


        /****** 上传文件 ******/

        // 方法 1
        // 获取hdfs的输出流
        FSDataOutputStream fos = fileSystem.create(new Path("/file.txt"));
        // 获取本地输入流
        FileInputStream fis = new FileInputStream("C:\\file.txt");
        // 通过将文件从输入流复制到输出流从而实现上传
        IOUtils.copyBytes(fis, fos, 1024, true);

        // 方法 2
        fileSystem.copyFromLocalFile(
                new Path("C:\\Users\\dev\\.ssh\\config"),
                new Path("/config.txt")
        );

        /****** 下载文件 ******/

        // 方法 1
        fileSystem.copyFromLocalFile(
                new Path("/file.txt"),
                new Path("c:\\file.txt")
        );

        // 方法 2
        FSDataInputStream fsDataInputStream = fileSystem.open(new Path("/file.txt"));
        FileOutputStream fileOutputStream = new FileOutputStream("C:\\file.txt");
        IOUtils.copyBytes(fsDataInputStream, fileOutputStream, 1024, true);

        /****** 删除文件 ******/
        // 第二个参数用于指定是否递归删除,用于删除目录
        boolean flag = fileSystem.delete(new Path("/file.txt"), true);
        if (flag) {
            System.out.println("success");
        } else {
            System.out.println("failed");
        }
    }
}

HDFS 体系

主从结构,主节点称为NameNode用于管理,支持多个;从节点称为DataNode,支持多个;SecondaryNameNade进程

  1. NameNode :整个文件系统的管理节点,主要维护文件系统的文件目录树,文件/目录的信息,每个文件对应的数据库列表(大文件分割存储),并还负责接收用户操作的请求
    包含以下文件 fsimage  edits  seed_txid  VERSION
    文件位置由 $HADOOP_HOME/share/hadoop/hadoop-hdfs-3.3.1.jarhdfs-default.xmldfs.namenode.dir 确定。默认为 file://${hadoop.tmp.dir}/dfs/name
    每次NameNode启动的时候都会将Fsimage文件读入内存,加载Edits里面的更新操作,保证内存中的元数据信息是最新的、同步的,可以看成NameNode启动的时候就将Fsimage和Edits文件进行了合并。
    hdfs-default.xml默认配置了配置项,hdfs-site.xml 是对这个配置文件的扩展。

    文件类型 用途
    fsimage 文件系统元数据的一个永久性的检查点,其中包含HDFS文件系统的所有目录和文件inode的序列化信息。hdfs oiv -p XML -i fsimage_00000000056 -o fsimage56.xml读取fsimage文件,信息输出到xml格式中。fsimage保存的是文件和block块的信息。
    edits

    事务文件,存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有操作首先会被记录到Edits文件中。Edits文件中数据定时合并到fsimage中,这个定期任务由SecondaryNameNode进程完成。生产环境中SecondaryNameNode要部署到一个单独的机器上。已上传的固化文件记录在fsimage中,正在上传的文件记录在edits中。hdfs oev -i deits_00000000000057 -o edits.xml查看edits文件

    seed_txid 保存的是一个数字,就是最后一个edits_的数字
    VERSION  版本,格式化文件系统时这个文件内容会变
  2. DataNode :提供真实文件数据的存储服务,由 dfs.datanode.data.dir 指定位置,默认 file://${hadoop.tmp.dir}/dfs/data
    HDFS会按照固定的大小, 顺序对文件进行划分并编号,划分 好的每一个块称一个Block,HDFS默认Block大小是128MB;如果一个文件小于一个数据块的大小, 那么并不会 占用整个数据块的存储空间
    Replication:多副本机制,默认副本数为3,通过 dfs.replication 属性控制,用于保证数据安全。
  3. SecondaryNameNode :
    主要负责定期的把edits文件中的内容合并到fsimage中;这个合并操作称为checkpoint,在合并的时候会对edits中的内容进行转换,生成新的内容保存到fsimage文件中;注意: 在NameNode的HA架构(多个NameNode)中没有SecondaryNameNode 进程, 文件合并操作会由standby NameNode负责实现

 

数据具体存储在哪个DataNode只有DataNode自己知道,DataNode启动后扫描自己的block块,然后将节点信息和block块信息告诉NameNode。集群每次启动都扫描数据,所以数据越多启动越慢。这里是block与节点之间的关系,与 fsimage 关联后可以根据文件找到对应的block块,再根据block块找到DataNode节点。

NameNode维护了两份关系:

  1. 文件和block块的联系,对应的关系信息存储在 fsimage和edits文件中(当NameNode启动的时候会把文件中 的元数据信息加载到内存中,每个文件元数据占用150字节的内存,故不适合小文件)
  2. block块与DataNode的联系,(当DataNode启动时 会把当前节点上的Block信息和节点信息上报给NameNode)

 

HDFS 回收站

hdfs中删除的文件会进入回收站,一段时间后彻底删除。默认没有开启,通过配置所有节点的 core-site.xml 开启回收站。

<property>
    <name>fs.trash.interval</name>
    <value>1440</value>      <!-- 单位为分钟,0为关闭 -->
</property>

回收站位于 hdfs://ip:port/user/root/.Trash/Current/filename。如果要恢复,可以通过移动到其他目录或下载到本地。回收站目录就是一个有特殊含义的目录。如果删除的文件过大可能删除失败,此时要使用 hdfs dfs -rm -skipTrash /file.txt直接删除。

 

HDFS 安全模式

集群刚启动时HDFS会进入安全模式,此时无法执行写操作。查看安全模式 hdfs dfsadmin -safemode get手动离开安全模式hdfs dfsadmin -safemode leave

 

HDFS 高可用 高扩展

 

NameNode 节点宕机怎么办?

NameNode有一个工作状态,其余的都是备用状态。ActiveNameNode负责所有客户端的操作,StandbyNameNode用来同步ActiveNameNode的状态信息以提供快速故障恢复的能力。且HA模式下不能启动SecondaryNameNode,会出错。

为了使多个NameNode状态同步,DataNode同时向多个NamdNode发送信息;此外还有一群独立的守护进程JournalNode用于同步Active NameNode信息,standby NameNode 观测JournalNode的变化并更新自身。如果Active NameNode宕机,StandyNameNode要保证从JournalNode读取到全部信息并变为Active状态。同步数据包括静态和动态的,静态的包括fsimage和edits,而fsimage由edits合并而成,故只需edits同步即可,JournalNode就是用于同步edits文件。

当active宕机时,NameNode的切换可以自动也可手动。自动需要使用zookeeper集群,NameNode启动后会到zk中注册,宕机后zk会检测到并进行active的切换。

 

NameNode节点内存不够用怎么办?

同一集群中每个NameNode的信息都是相同的,所以一个集群能够存储的信息由一个NameNode的大小决定。

高扩展(Federation)解决单一命名空间的一些问题,提供了以下特性:HDFS集群拓展、性能更高效、良好的隔离性。

NN1与NN2同属一个命名空间(也就是同一目录下),所以二者信息相同。NN2与NN4同属一个命名空间。后续存储数据时通过命名空间进行区分。此处一个Federation的存储空间等于两个命名空间也就是两个NameNode的大小。

 

定时上传数据到HDFS

要求:每天凌晨将昨天生成的日志文件上传到HDFS的以日期命名的目录中。

思路:

  1. 获取到昨天日志文件的名称
  2. 在HDFS上使用昨天日期创建目录
  3. 将昨天的日志文件上传到刚创建的HDFS目录中
  4. 要考虑脚本重跑,补数据的情况
  5. 配置crontab
#!/bin/bash

# 接收参数指定日期,默认使用昨天日期字符串
yesterday=$1
if [ "$yesterday" = "" ]
then
    yesterday=`date +%Y_%m_%d --date="1 day ago"`
fi

# 拼接日志文件路径信息
logPath=/data/log/access_${yesterday}.log

# hdfs目录
hdfsPath=/log/${yesterday//_/}  # 字符串替换,将所有_替换为空格

# 在hdfs上创建目录
hdfs dfs -mkdir -p ${hdfsPath}

# 上传文件到hdfs文件系统
hdfs dfs -put ${logPath} ${hdfsPath}

 

标签:HDFS,文件,hdfs,dfs,file,NameNode
来源: https://www.cnblogs.com/zhh567/p/16316991.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有