一、入门

1.简介

HDFS: 全称Hadoop Distributed File System 中文:hadoop分布式文件系统
说明:HDFS是hadoop内的一个子技术
作用: 解决海量数据存储问题
特点:分布式文件存储系统(多台计算机联合存储)  突破单体服务器的存储瓶颈

2.HDFS体系架构

HDFS核心进程

一个HDFS集群的主节点, 一个集群只有1个.
1. 基于【内存】存储管理文件的【元数据】信息。(NameNode内存要求高。)
   文件名     类型 大小   权限      用户   组 
   ceshi.log 文件 500MB rwxrwxrwx root  root
2. 是HDFS集群的管理者master:管理集群中所有的datanode。
   datanode12 ip地址 磁盘容量 磁盘使用情况
   datanode13 ip地址 磁盘容量 磁盘使用情况
   目的:掌握datanode健康状况,了解磁盘容量,数据分布的负载均衡。
      均衡使用datanode的磁盘空间。
      集合多个datanode服务器的网络带宽,提高数据传输速度。
3. 接受客户端文件操作的请求(文件元数据操作请求)。
4. NameNode存储了文件拆分后的block分布信息:
   block0--[ip1,ip2]--起始位置--大小--checksum
   block1--所在dn的ip--起始位置--大小--checksum

# DataNode
HDFS集群的从节点, 一个集群有多个.
1. 管理存储数据文件切分后的block(128MB),存放硬盘上。廉价机器。
2. 是HDFS的从机,slave(workers)打工人
    heartBeat: 定期向namenode发送心跳(3s),告知datanode(ip 磁盘容量),如果超过10分钟,无心跳,则NameNode认为datanode死亡
    blockreport: 定期上报datanode中的存储的block的信息:
    发送 dn1上存储的所有文件的block的信息,如果NameNode没有收到的block信息,则判断该block在该dn上失效。
    block汇报时间间隔取参数dfs.blockreport.intervalMsec,参数未配置的话默认为6小时。
3. 接收数据data block上传下载的客户端请求。

HDFS核心概念

# block: 文件切分后的数据块。
     大小默认128MB
     原因:现有服务器机房局域网网络带宽千兆带宽==125MB/s
     说明:
     block过大:导致单个block通过磁盘和网络读取读取时间过长,影响该部分数据的处理速度,并且增加单个        block传输的失败几率,重试成本过高,浪费IO资源。
     block过小:block个数过多,导致namenode内存过度占用,导致不足。
     结论:100MB/s的带宽,block设置为128MB
          220MB/s左右的带宽,block设置为256MB.
         
# replication:副本(副本因子)
     每个block在hdfs的datanode会存储多份。默认replication=3,每个block有3份。
     原因:防止datanode因为单点故障,导致数据丢失。
     实战参数:一般block的replication就是3个。
 
# checksum:校验和
    datanode定期,计算本节点存储的block的checksum,判断是否和之前的checksum保持一致。
    说明:datanode掌握block文件是否损坏的判断手段。

二、安装(伪分布式)

服务器准备

# 0. 准备虚拟机
# 1. 设置hostname
    hostnamectl set-hostname hadoop10
# 2. 配置hosts(linux+windows)
    vim /etc/hosts
    ----------以下是文件信息------------
    192.168.199.10 hadoop10
    补充:
      一定要配置windows对集群中所有节点的映射关系。
# 3. 关闭防火墙
    systemctl stop firewalld #关闭防火墙
    systemctl disable firewalld # 禁止防火墙开机启动。
# 4. 安装jdk1.8
    [root@hadoop10 modules]# tar -zxvf jdk-8u171-linux-x64.tar.gz -C /opt/installs/
    [root@hadoop10 installs]# mv jdk1.8.0_171/ jdk1.8
# 5. 配置jdk环境变量。
     [root@hadoop10 installs]# vim /etc/profile
      # JAVA
      # JAVA_HOME
      export JAVA_HOME=/opt/installs/jdk1.8
      # PATH
      export PATH=$PATH:/opt/installs/jdk1.8/bin/
      加载配置
      source /etc/profile
      验证 
      java 
# 6. 配置 hadoop10到hadoop10 免密动作  
     ssh-keygen
     ssh-copy-id hadoop10

安装

1.解压、配置环境变量

# 解压
  [root@hadoop10 modules]# tar -zxvf hadoop-3.1.4.tar.gz -C /opt/installs/
  [root@hadoop10 installs]# mv hadoop-3.1.4 hadoop3.1.4
# 配置环境变量
  vim /etc/profile
  -------------以下是环境变量-------------
  # 配置HADOOP_HOME
  export HADOOP_HOME=/opt/installs/hadoop3.1.4
  # 配置PATH
  export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
# 生效配置信息(重新执行profile中的指令,加载配置信息)
  source /etc/profile
# hadoop目录结构(tree命令可以通过yum install -y tree安装)
[root@hadoop10 ~]# tree -L 1 /opt/installs/hadoop3.1.4/
/opt/installs/hadoop3.1.4/
├── bin # hadoop客户端操作相关的脚本程序,hdfs、hadoop、yarn
├── etc # 配置目录xml、文本文件   [重要]
├── include # 一些C的头文件,无需关注
├── lib # 第三方native实现C实现
├── libexec # hadoop运行时候,加载配置的脚本
├── LICENSE.txt
├── logs # 系统运行日志目录,排查故障!  [重要]
├── NOTICE.txt
├── README.txt
├── sbin # hadoop服务器端操作相关脚本,通常用于启动服务例如:start-dfs.sh|stop-dfs.sh
└── share # hadoop运行的依赖jars、内嵌webapp 
 |----data目录  (hadoop运行数据)

2.初始化配置文件($HADOOP_HOME/etc/hadoop)

hadoop-env.sh — hadoop环境配置(jdk)
core-site.xml — Hadoop核心配置文件
hdfs-site.xml — HDFS的个性化配置文件 副本因子
works         — 在哪个节点启动datanode

# hadoop-env.sh
    # jdk安装目录
    export JAVA_HOME=/opt/installs/jdk1.8
    
    export HDFS_NAMENODE_USER=root
    export HDFS_DATANODE_USER=root
    export HDFS_SECONDARYNAMENODE_USER=root

# core-site.xml
  <!-- HDFS的入口,将来会在这个机器上启动namenode,上传下载通过8020端口 -->
  <property>
    <name>fs.defaultFS</name>
    <value>hdfs://hadoop10:8020</value>    
  </property>
  <!-- 配置 数据保存位置(hadoop的根目录下新建data目录,会自动创建)-->
  <property>
    <name>hadoop.tmp.dir</name>
    <value>/opt/installs/hadoop3.1.4/data</value>
  </property>
  
# hdfs-site.xml
  <property>
    <name>dfs.replication</name>
    <value>1</value>
  </property>
  
  <property>
    <name>dfs.namenode.secondary.http-address</name>
    <value>hadoop10:9868</value>
  </property>

   <property>
     <name>dfs.permissions.enabled</name>
     <value>false</value>
     <description>如果为"true",则在HDFS中启用权限检查;如果为"false",则关闭权限检查;默认值为"true"。</description>
 </property> 
  
# workers
# 配置从机datanode的ip
hadoop10

3.格式化HDFS(第一次安装HDFS 格式化文件系统)

# 一旦hadoop配置启动失败,清空data下的文件,再重新格式化。
#初始化namenode和datanode存放数据的目录
hdfs namenode -format

4.启动HDFS

# 启动hdfs
  start-dfs.sh
# 关闭hdfs
  stop-dfs.sh
  
# 启动namenode
hadoop-daemon.sh start namenode

# 启动datanode
hadoop-daemon.sh start datanode

5.验证

# 查看hdfs进程
[root@hadoop10 installs]# jps
2225 NameNode  # master namenode主机
4245 Jps
2509 SecondaryNameNode 
2350 DataNode  # slave datanode从机

# 查看hdfsWeb服务
1. 查看namenode的web服务
  http://hadoop10:9870/   (hadoop2.x默认端口号是50070)
  
2. 查看datanode的Web服务
  http://hadoop10:9864/   (hadoop2.x默认端口号是50075)

搭建知识补充:

1.日志查看(查看hdfs运行异常)

# namenode启动运行日志
  hadoop-用户名-namenode-主机名.log
  
# datanode启动日志
  hadoop-用户名-datanode-主机名.log

2.HDFS配置错误修正

# 1. 关闭启动的hdfs程序
     stop-dfs.sh 
     
# 2. 修改错误的配置文件。

# 3. data目录清空,重新格式化
    hdfs namenode -format
    
场景: 格式化或者启动hadoop失败。
说明:
      hadoop/data文件夹
      作用: 保存datanode和namenode持久化的数据。
      时机:
        1. 格式化hdfs namenode -format 会初始化该目录下的文件。
        2. hdfs运行期间产生的数据,会操作该目录中的数据。
           必要操作:删除格式化或者启动数据保存的文件目录。

3.web界面

NameNode的web管理器地址:http://ip:9870

三、HDFS客户端操作

1.HDFS命令

# 1. 命令所在目录
   ${hadoop}/bin之下/hdfs
 
# 2. HDFS的文件系统结构
     和Linux类似。 
  
# 3. 命令格式
  hdfs   dfs -xxx -参数     hdfs  dfs  -put linux的文件  hdfs的路径
  hadoop fs  -xxx -参数     hadoop fs  -put linux的文件  hdfs的路径

2.常见命令

命令语法

含义

示例代码

hdfs dfs -ls [-R] hdfs文件路径

查看文件元数据信息

hdfs dfs -ls /

hdfs dfs -mkdir -p /目录a/目录b

新建文件夹,如果父目录不存在则添加-p参数

hdfs dfs -mkdir -p /file

hdfs dfs -put linux文件路径 hdfs目录

文件上传

hdfs dfs -put 本地文件 hdfs路径

hdfs dfs -get hdfs文件 linux目录

文件下载

hdfs dfs -get hdfs路径 本地文件

hdfs dfs -cat hdfs文档路径

查看文件内容

hdfs dfs -cat /Test.java

hdfs dfs -rm hdfs文件路径

删除文件

hdfs dfs -rm /Test.java

hdfs dfs -rm -r hdfs文件夹

删除文件夹,非空使用-rmr

hdfs dfs -rm -r /test1

hdfs dfs -chmod [-R] 权限运算值 hdfs文件 hdfs dfs -chmod [-R] u+x hdfs文件

修改hdfs文件权限

hdfs dfs -chmod o+w /test1

hdfs dfs -appendToFile linux本地A文件 HDFS远程B文件

将A文件内容追加到HDFS的B文件的末尾。

hdfs dfs -appendToFile /etc/profile /Test1.java

hdfs dfs -mv /hdfs/demo1/wordcount1.log /hdfs/demo2

移动HDFS文件系统内部文件

hdfs dfs -mv /hdfs/demo1/wordcount1.log /hdfs/demo2

hdfs dfs -getmerge

合并下载多个文件,要给定一个目录或者直接填写具体的每个文件

hdfs dfs -getmerge /hdfs文件夹 ./new.txt

hdfs dfs -getmerge /test.txt /test2.txt /要输出的本地路径

3.Java操作HDFS

  • 核心API

API

含义和作用

Configuration

配置信息,封装hdfs操作的相关配置文件信息

FileSystem

HDFS的分布式文件系统工具,操作HDFS文件。

PATH

表示操作路径

  • windows开发环境准备(开发和测试需要)

# 1. 将hadoop3.1.4的软件,解压到window中,路径不能有中文,不能有空格。
# 2. 拷贝hadoop的windows执行环境工具(winutils.exe)到bin路径下
# 3. 配置环境变量
  HADOOP_HOME=hadoop安装路径
  PATH=hadoop安装路径/bin
# 4. 重启IDEA
  • 添加log4j.properties

  • HDFS依赖

<dependencies>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-client</artifactId>
        <version>3.1.4</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>
  • 编程步骤(文件上传)

/**
* 需求:向hdfs集群上传一个文件?
*
* 命令:hdfs dfs -put 本地文件路径  hdfs远程路径位置。
*/
@Test
public void test1() throws IOException {
    // 1. 初始化配置
    Configuration conf = new Configuration();
    conf.set("fs.defaultFS", "hdfs://hadoop10:8020");
    // 2. 获得操作hdfs的客户端。
    FileSystem fs = FileSystem.get(conf);
    // 使用客户端的方法(命令),操作hdfs
    fs.copyFromLocalFile(new Path("D:/xxx.txt"), new Path("/"));
    // 3. 关闭资源。
    if (fs != null) {
        fs.close();
    }
}
异常: Permission denied: user=Administrator, access=WRITE, inode="/hdfs":root:supergroup:drwxr-xr-x
解决办法: 为上传的hfds目录添加写w权限 hdfs dfs -chmod -R 777 /
  • 其他API操作

/**
* 需求:从hdfs中下载 /demo.tar.gz 文件?
* 命令:hdfs dfs -get /demo.tar.gz  D:/
*/
@Test
public void test2() throws IOException {
    //1. 初始化配置文件
    Configuration conf = new Configuration();
    conf.set("fs.defaultFS", "hdfs://hadoop10:8020");

    //2. 获得hdfs操作客户端
    FileSystem fs = FileSystem.get(conf);
    fs.copyToLocalFile(new Path("/demo.tar.gz"), new Path("D:/demo.tar.gz"));// 拷贝到本地。
    //
    //3. 关闭资源
    fs.close();
}


//返回值boolean,是否创建成功。 
boolean isok = fileSystem.mkdirs(new Path("/test1"));

//判断文件是否存在
boolean isexist = fileSystem.exists(new Path("/test1"));

/**
删除文件
参数1:远端hdfs的文件路径
参数2:是否递归删除,如果给false,删除无法递归则会抛出异常
返回值:是否删除成功
*/
Boolean deleteOK = fileSystem.delete(new Path("hdfs文件路径"),true);    
//3.调接口
// hdfs dfs -ls /xx 查看文件列表的元数据信息
FileStatus[] fileStatuses = fileSystem.listStatus(new Path("/xx"));
for (FileStatus fileStatus : fileStatuses) {
    System.out.println(fileStatus.getPath());
    System.out.println(fileStatus.getLen());
    System.out.println(fileStatus.getBlockSize());
}


//---------

//3.调接口
// hdfs dfs -ls -R /xx 查看文件列表的元数据信息
// hdfs dfs -ls -R/xx

RemoteIterator<LocatedFileStatus> listFiles = fileSystem.listFiles(new Path("/xx"), true);
while (listFiles.hasNext()) {
    LocatedFileStatus fileStatus = listFiles.next();
    System.out.println(fileStatus.getPath());
    // -- 查看block 块 的位置信息: 起始位置,大小,服务器
    BlockLocation[] locations = fileStatus.getBlockLocations();
    for (BlockLocation location : locations) {
        System.out.println(location);
    }
    System.out.println("------------");
}

四、HDFS原理相关

1.Trash回收站

HDFS为了规避由于用户的误操作,导致的数据删除丢失,用户可以在构建HDFS的时候,配置HDFS的垃圾回收功能。
所谓的垃圾回收,本质上是在用户删除文件的时候,系统并不会立即删除文件,仅仅是将文件移动到垃圾回收的目录。
然后更具配置的时间,一旦超过该时间,系统会删除该文件,用户需要在到期之前,将回收站的文件移除垃圾站,即可避免删除
<!--开启垃圾回收,需要在core-site.xml中添加如下配置,然后重启hdfs即可-->
<!--垃圾回收,1440 minites == 1天-->
<property>
  <name>fs.trash.interval</name>
  <value>1440</value>
</property>
# 验证(日志会记录文件删除的回收站的位置)
[root@hadoop10 hadoop]# hdfs dfs -rm -r /Test1.java
20/11/13 18:28:50 INFO fs.TrashPolicyDefault: Moved: 'hdfs://hadoop10:8020/Test1.java' to trash 
at: hdfs://hadoop10:8020/user/root/.Trash/Current/Test1.java
# 恢复回收站数据(本质上就是移动文件)
hdfs dfs -mv /user/root/.Trash/Current/Test1.java / 

2.NameNode持久化

  • 场景引入

# 问题:NameNode宕机,导致内存中的文件元数据丢失怎么办?
# 解决:NameNode会将内存中的元数据持久化到磁盘中。 
  • 持久化方案分析

  • 持久化结论

# 1. HDFS接受客户端的文件操作后。
# 2. 先将操作的命令 以日志的方式记录到editslog中。
# 3. 然后再将指令对应的文件元数据的修改操作,修改内存中的元数据信息。
# 4. SNN定期负责将editslog中的文件合并到fsimage中。

3.checkpoint机制

  • 生活案例

  • SNN的checkpoint工作机制

1. SecondaryNameNode向NameNode发起合并请求
2. NameNode将当前的Editslog文件保存改名edits,并新建EditsLog继续持久化工作。
3. 将改名后的edits文件和本地的FSImage(旧)发送给sencondaryNameNode
4. SecondaryNameNode负责将FSImage(旧)+edits文件合并成FSImage(新)
5. 将新的FSImage(新)发送给NameNode保存。

  • checkpoint触发条件(时机)

# 每1分钟检查一次触发条件。(SNN每隔1分钟,访问一次NN)
1. 每隔1小时触发一次checkPoint
2. 每100w次操作,触发一次checkpoint
下面的配置信息对应hdfs-site.xml

name

value默认

含义

dfs.namenode.checkpoint.period

3600

3600秒触发一次,数据合并。checkpoint

dfs.namenode.checkpoint.txns

1000000

100w次操作触发一次

dfs.namenode.checkpoint.check.period

60

1分钟检查一次操作次数

  • SecondaryNameNode节点定制

SNN和NN在一个服务器上时,存在单点故障。
场景:一旦服务器磁盘崩坏,持久化的数据就会全部丢失。
解决:SNN 和NN放在不同的服务器上。

4.HDFS启动流程-NameNode安全模式(SafeMode)

# 时机
HDFS启动过程中, 会进入一个特殊状态(SafeMode),该状态下NameNode暂停接受客户端文件修改操作(只能接收文件读操作)
# HDFS启动流程-启动过程自动完成。
1. NameNode启动,加载最新的fsimage恢复数据,并加载未合并的editslog_inprogress,进一步恢复数据。--- NN管理内存数据完整。
2. 等待接受DataNode的心跳 HeartBeat 
    DN的本节点地址 健康状态 磁盘容量 剩余容量 版本号。
3. 等待接受DataNode的块报告 Block Report,判断是否满足最小副本因子(默认值1 dfs.namenode.replication.min),达到了, 则认为当前Block是安全的,完整的。
    DN的本节点的内全部Block的信息: block的id offset length。
4. NameNode发现HDFS集群中所有的block的安全(完整)比例是否达到99.9%(dfs.namenode.safemode.threshold-pct), 如果达到,则立刻退出安全模式。
      ① 为什么要设置最小副本因子为1: 只要有1块完整,block数据即是完整,没必要等全部完整。
5. HDFS退出安全模式,才能正常工作。 

导致HDFS无法退出安全模式的原因:
实战开发角度:
1. block块不完整
   产生的原因:例如,hdfs运行的过程中,意外中断。
   解决方案:关闭安全模式
            如果是某个块有问题, 但是副本可用,HDFS可以自行解决
            如果这个块没有可用副本,删除块对应的副本
  
2. DataNode依赖的硬盘资源不够,例如磁盘使用比率达到90% 、NameNode的内存不够用
    第二种情况进入安全模式后,即便退出,稍后会立刻自动在进入安全模式
    如果硬盘不够用,可以挂载新的硬盘或者删除硬盘上的文件
    如果内存不够用,删除HDFS上的文件或者是合并小文件成大文件  

# 手动安全模式
  理由:实际开发中为了对HDFS进行维护,会手动NameNode进入安全模式
  注意:safemode安全模式下,只能对HDFS中文件进行读操作,不能进行写操作(上传 修改 删除 移动)
  
0. 查看hfds安全模式状态
hdfs dfsadmin -safemode get
1. 进入安全模式
hdfs dfsadmin -safemode enter
2. 退出安全模式
hdfs dfsadmin -safemode leave

5.文件上传流程

7.文件下载流程

五、HDFS完全分布式集群搭建

1.SSH免密登录

2.HDFS分布式集群搭建

1.集群规划

2.免密登录设置

1. 生成秘钥
[root@hadoop11 hadoop]# ssh-keygen

2. 发送公钥到集群所有节点 hadoop11 hadoop12 hadoop13
[root@hadoop11 hadoop]# ssh-copy-id hadoop11
[root@hadoop11 hadoop]# ssh-copy-id hadoop12
[root@hadoop11 hadoop]# ssh-copy-id hadoop13

3. 验证免密登录效果
ssh root@hadoop13

防火墙

/etc/hosts ip和主机名映射

3.安装HDFS(1台)

1. 解压hadoop
2. 配置环境变量
   HADOOP_HOME
   PATH
3. 重新加载配置文件

4.初始化配置文件(1台)

1. hadoop-env.sh
    export JAVA_HOME=/opt/installs/jdk1.8
    
    export HDFS_NAMENODE_USER=root
    export HDFS_DATANODE_USER=root
    export HDFS_SECONDARYNAMENODE_USER=root
        
2. core-site.xml
  <property>
    <name>fs.defaultFS</name>
    <value>hdfs://hadoop11:8020</value>    
  </property>
  <property>
    <name>hadoop.tmp.dir</name>
    <value>/opt/installs/hadoop3.1.4/data</value>
  </property>
  
3. hdfs-site.xml
  <property>
        <name>dfs.replication</name>
        <value>2</value>
  </property>
  
  <property>
        <name>dfs.namenode.secondary.http-address</name>
        <value>hadoop12:9868</value>
  </property>
  
  <property>
     <name>dfs.permissions.enabled</name>
     <value>false</value>
     <description>如果为"true",则在HDFS中启用权限检查;如果为"false",则关闭权限检查;默认值为"true"。</description>
 </property> 
  
4. workers (配置多个DN节点)
   DN节点所在主机的IP 
   hadoop11
   hadoop12
   hadoop13

5.同步配置文件到其他节点

# 注意事项
  一个hadoop集群中,所有hadoop配置文件要完全一致。
  将本机的hdfs配置同步到其他机器。
  /etc/profile 环境变量配置文件也需要发送
  如果有对配置的变动,一定要及时同步相应的配置文件

6.初始化HDFS集群

# 5. 初始化HDFS
  1. 删除hadoop的data文件夹(如果没有就算了)
  2. 格式化集群
     在namenode节点执行格式化(hadoop11)。
     hdfs namenode -format

7.配置windows访问HDFS的集群的ip映射 (C:\Windows\System32\drivers\etc\hosts)

192.168.152.10 hadoop10
192.168.152.11 hadoop11
192.168.152.12 hadoop12
192.168.152.13 hadoop13

8.启动HDFS

在拥有免密登录权限的节点上执行:
start-dfs.sh 

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐