HADOOP学习笔记之HDFS

简介: Hadoop Distributed File System,简称 HDFS,是一个分布式文件系统;

概述

Hadoop Distributed File System,简称 HDFS,是一个分布式文件系统;

  1. NameNode:存储文件的元数据,如文件名、文件目录结构、文件属性,以及每个文件的快列表和快所在的DataNode;
  2. DataNode:在本地文件系统存储文件快数据,以及块数据的校验和;
  3. Secondary NameNode:每隔一段时间对NameNode元数据备份;

优缺点

优点

  1. 高容错率:
  1. 数据自动保存多个副本。它通过增加副本的形式提高容错性。
  2. 某一个副本丢失以后,它可以自动恢复。
  1. 适合处理大数据
  1. 数据规模:能够处理数据规模达到GB、TB、甚至PB级别的数据;
  2. 文件规模:能够处理百万规模以上的文件数量,数量相当之大。
  1. 可构建在廉价机器上,通过多副本机制,提高可靠性。

缺点

  1. 不适合低延时数据访问,比如毫秒级的存储数据,是做不到的。
  2. 无法高效的对大量小文件进行存储。
  1. 存储大量小文件的话,它会占用NameNode大量的内存来存储文件目录和块信息。这样是不可取的,因为NameNode的内存总是有限的;
  2. 小文件存储的寻址时间会超过读取时间,它违反了HDFS的设计目标。
  1. 不支持并发写入、文件随机修改。
  1. 一个文件只能有一个写,不允许多个线程同时写
  2. 仅支持数据append(追加),不支持文件的随机修改。

HDFS组成架构

官方参考链接:https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html#Introduction

  1. NameNode (nn):就是Master,它是一个主管、管理者。
  1. 管理HDFS的名称空间;
  2. 配置副本策略;
  3. 管理数据块(Block)映射信息;
  4. 处理客户端读写请求。
  1. DataNode:就是Slave。NameNode下达命令,DataNode执行实际的操作。
  1. 存储实际的数据块;
  2. 执行数据块的读/写操作。
  1. Secondary NameNode:并非NameNode的热备。当NameNode挂掉的时候,它并不能马上替换NameNode并提供服务。
  1. 辅助NameNode,分担其工作量,比如定期合并Fsimage和Edits,并推送给NameNode ;
  2. 在紧急情况下,可辅助恢复NameNode。
  1. Client:就是客户端。
  1. 文件切分。文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行上传;
  2. 与NameNode交互,获取文件的位置信息;
  3. 与DataNode交互,读取或者写入数据;
  4. Client提供一些命令来管理HDFS,比如NameNode格式化命令;
  5. Client可以通过一些命令来访问HDFS,比如对HIDFS增删查改操作;


HDFS配置文件优先级

代码中 Configuration 对象中配置 > 在项目资源目录下得配置文件 > hdfs-site.xml > hdfs-default.xml


HDFS文件块大小

HDFS中的文件在物理上是分块存储(Block),块的大小可以通过 hdfs-default.xml 中配置参数 dfs.blocksize 配置,默认大小在Hadoop2.x/3.x版本中是128M,1.x版本中是64M;

注:hdfs-default.xml 在 $HADOOP_HOME/share/hadoop/hdfs 目录下的 hadoop-hdfs-3.2.3.jarJAR内,需要解压才能查看;

  • 如果寻址时间约为10ms,即查找到目标block的时间为10ms。
  • 寻址时间为传输时间的1%时,则为最佳状态。
  • 而目前磁盘的传输速率普遍为100MB/s。


思考:为什么块的大小不能设置太小,也不能设置太大?

  1. HDFS的块设置太小,会增加寻址时间,程序一直在找块的开始位置;
  2. 如果块设置的太大,从磁盘传输数据的时间会明显大于定位这个块升始位置所需的时间。导致程序在处理这块数据时,会非常慢。

总结:HDFS块的大小设置主要取决于磁盘传输速率。

HDFS 的 Shell 操作

格式

  1. hadoop fs 具体命令
  2. hdfs dfs 具体命令
# HDFS 直接操作## 创建文件夹(保持完整文件目录)hadoop fs -mkdir /文件夹名称
示例:hadoop fs -mkdir /sanguo
## 查询目录下所有文件夹和文件信息hadoop fs -ls 文件夹全路径
示例:hadoop fs -ls /
## 显示文件内容hadoop fs -cat 文件全路径
示例:hadoop fs -cat /sanguo/shuguo.txt
## 修改文件所述权限(-chgrp/-chmod/-chown,和linux系统中的用法一样)示例:hadoop fs -chmod777## 从 HDFS 的一个路径拷贝到 HDFS 的另一个路径hadoop fs -cp 原全路径 目标全路径
示例:hadoop fs -cp /sanguo/shuguo.txt /jinguo
## 在 HDFS 目录中移动文件hadoop fs -mv 原全路径 目标路径
示例:hadoop fs -mv /sanguo/wuguo.txt /jinguo
## 显示一个文件的末尾 1kb 的数据hadoop fs -tail 文件全路径
示例:hadoop fs -tail /jinguo/shuguo.txt
## 删除文件或者文件夹hadoop fs -rm 文件全路径或者文件夹全路径
示例:hadoop fs -rm /jinguo/shuguo.txt
## 递归删除目录及目录里的内容hadoop fs -rm-r 文件夹全路径
示例:hadoop fs -rm-r /sanguo
## 统计文件夹的大小信息hadoop fs -du 文件夹全路径
示例:hadoop fs -du /jinguo
## 设置 HDFS 中文件的副本数量hadoop fs -setrep 副本数量 文件全路径
示例:hadoop fs -setrep10 /jinguo/wuguo.txt
# 上传## 从本地剪切粘贴到 HDFS 中hadoop fs -moveFromLocal 文件 目标文件夹
示例: hadoop fs -moveFromLocal shuguo.txt /sanguo
## 从本地文件系统中拷贝文件到 HDFS 中(put 相当于 copyFromLocal)hadoop fs -put 文件 目标文件夹
示例:hadoop fs -put wuguo.txt /sanguo
hadoop fs -copyFromLocal 文件 目标文件夹
示例:hadoop fs -copyFromLocal weiguo.txt /sanguo
## 最佳一个文件到已经存在的文件末尾hadoop fs -appendToFile 文件 目标文件
示例:hadoop fs -appendToFile liubei.txt /sanguo/shuguo.txt
# 下载## 从 HDFS 拷贝到本地hadoop fs -copyToLocal 文件全路径 目标目录
示例:hadoop fs -copyToLocal /sanguo/shuguo.txt .
hadoop fs -get 文件全路径 目标目录
示例:hadoop fs -get /sanguo/shuguo.txt .

HDFS API操作

maven 依赖

<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-client --><dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-client</artifactId><version>3.2.3</version></dependency>

具体操作

packagetop.simba1949;
importlombok.extern.slf4j.Slf4j;
importorg.apache.hadoop.conf.Configuration;
importorg.apache.hadoop.fs.*;
importjava.net.URI;
importjava.util.Arrays;
/*** 客户端代码步骤* 1. 获取客户端对象(和 NameNode 连接)* 2. 执行相关命令* 3. 关闭资源* @author SIMBA1949* @date 2022/7/12*/@Slf4jpublicclassApplication {
publicstaticvoidmain(String[] args) throwsException {
// hadoop 集群中 NameNode 地址URIuri=newURI("hdfs://hadoop1:8020");
// 配置文件信息Configurationconfiguration=newConfiguration();
// 获取到客户端对象FileSystemfileSystem=FileSystem.get(uri, configuration, "root");
// 操作命令fileOrFolder(fileSystem);
// 关闭资源fileSystem.close();
    }
/*** 创建文件夹* @throws Exception*/publicstaticvoidmkdirs(FileSystemfileSystem) throwsException {
// 创建文件夹命令fileSystem.mkdirs(newPath("/xiyou/huoguoshan"));
    }
/*** 上传文件* @param fileSystem*/publicstaticvoidcopyFromLocalFile(FileSystemfileSystem) throwsException {
// 第一个参数:表示是否删除原数据,第二个参数:表示是否允许覆盖// 第三个参数:表示源路径,第四个参数:表示目标路径Pathsrc=newPath("D:/BigData/hdfs-test-workspace/sunwukong.txt");
Pathdst=newPath("/xiyou/huoguoshan");
fileSystem.copyFromLocalFile(true, true, src, dst);
    }
/*** 下载文件* @param fileSystem* @throws Exception*/publicstaticvoidcopyToLocalFile(FileSystemfileSystem) throwsException {
Pathsrc=newPath("/xiyou/huoguoshan/hdfs-test-workspace"); // 源路径Pathdst=newPath("D:/BigData/"); // 目标路径// 第一个参数:表示是否删除// 第二个参数:表示源路径,第三个参数:表示目标路径// 第四个参数:表示开启本地校验fileSystem.copyToLocalFile(true, src, dst, true);
    }
/*** 删除文件* @param fileSystem* @throws Exception*/publicstaticvoiddelete(FileSystemfileSystem) throwsException {
// 第一个参数:表示删除的路径// 第二个参数:表示是否递归删除booleanblDelete=fileSystem.delete(newPath("/xiyou"), true);
if (blDelete){
log.info("/xiyou 已经删除成功");
        }
    }
/*** 重命名* @param fileSystem* @throws Exception*/publicstaticvoidrename(FileSystemfileSystem) throwsException {
Pathsrc=newPath("/input/word.txt"); // 源路径Pathdst=newPath("/input/word-copy.txt"); // 目标路径// 第一个参数:表示源路径,第二个参数:表示目标路径fileSystem.rename(src, dst);
    }
/*** 移动并重命名* @param fileSystem* @throws Exception*/publicstaticvoidmoveAndRename(FileSystemfileSystem) throwsException {
Pathsrc=newPath("/input/word-copy.txt"); // 源路径Pathdst=newPath("/word-copy-copy.txt"); // 目标路径// 第一个参数:表示源路径,第二个参数:表示目标路径fileSystem.rename(src, dst);
    }
/*** 获取文件信息* @param fileSystem* @throws Exception*/publicstaticvoidgetFileInfo(FileSystemfileSystem) throwsException {
// 第一个参数:表示目标路径,第二个参数:表示是否递归RemoteIterator<LocatedFileStatus>listFilesIterator=fileSystem.listFiles(newPath("/"), true);
while (listFilesIterator.hasNext()) {
LocatedFileStatuslocatedFileStatus=listFilesIterator.next();
log.info("the file what [{}]", locatedFileStatus);
BlockLocation[] blockLocations=locatedFileStatus.getBlockLocations();
log.info("the file block what [{}]", Arrays.toString(blockLocations));
        }
    }
/*** 文件、文件夹的判断* @param fileSystem* @throws Exception*/publicstaticvoidfileOrFolder(FileSystemfileSystem) throwsException {
// 第一个参数:表示目标路径FileStatus[] fileStatuses=fileSystem.listStatus(newPath("/"));
for (FileStatusfileStatus : fileStatuses) {
Stringname=fileStatus.getPath().getName();
if (fileStatus.isFile()){
log.info("the path is file what [{}]", name);
            }else {
log.info("the path is folder what [{}]", name);
            }
        }
    }
}

HDFS的写数据流程


网络拓扑——节点距离计算

在 HDFS写数据的过程中,NameNode会选择距离待上传数据最近距离的DataNode接收数据。

节点距离:两个节点到达最近的共同祖先的距离总和。


机架感知(副本存储节点选择)

机架感知官方说明:https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html#Data_Replication

  1. 第一个副本在Client所处的节点上。如果客户端在集群外,随机选一个。
  2. 第二个副本在另一个机架的随机一个节点
  3. 第三个副本在第二个副本所在机架的随机节点



HDFS的读数据流程


NN 和 2NN 的工作机制


Fsimage 和 Edits 解析

NameNode被格式化之后,将在 ${HAOOP_HOME}/data/dfs/name/current目录中产生如下文件

fsimage_oooooooooooooooooo0
fsimage_ooo00000ooooo000000. md5
seen_txid
VERSION
  1. Fsimage文件: HDFS文件系统元数据的一个永久性的检查点,其中包含HDFS文件系统的所有目录和文件inode的序列化信息。
  2. Edits文件:存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先会被记录到Edits文件中。
  3. seen_txid文件保存的是一个数字,就是最后一个edits_的数字
  4. 每次 NameNode 启动的时候都会 将Fsimage 文件读入内存,加载 Edits 里面的更新操作,保证内存中的元数据信息是最新的、同步的,可以看成 NameNode 启动的时候就将 Fsimage 和 Edits 文件进行了合并。

查看文件命令

# 基本语法## 查看镜像文件hdfs oiv -p 文件类型 -i 镜像文件 -o 转换后文件输出路径
示例: 
cd /opt/bigdata/hadoop-3.2.3/data/dfs/name/current/
hdfs oiv -p XML -i fsimage_0000000000000000256 -o /opt/fsimage.xml
## 查看编辑日志hdfs oev -p 文件类型 -i 编辑日志 -o 转换后文件输出路径
示例:
cd /opt/bigdata/hadoop-3.2.3/data/dfs/name/current/
hdfs oev -p XML -i edits_0000000000000000001-0000000000000000154 -o /opt/edits.xml


CheckPoint 设置

CheckPoint 配置在hdfs-default.xml文件中。

1)通常情况下,SecondaryNameNode 每隔一小时执行一次

<property><name>dfs.namenode.checkpoint.period</name><value>3600</value><description>    The number of seconds between two periodic checkpoints.
    Support multiple time unit suffix(case insensitive), as described
    in dfs.heartbeat.interval.If no time unit is specified then seconds
    is assumed.
</description></property>

2)一分钟检查一次操作次数,当操作次数达到一百万次时,SecondaryNameNode 执行一次

<property><name>dfs.namenode.checkpoint.txns</name><value>1000000</value><description>The Secondary NameNode or CheckpointNode will create a checkpoint
  of the namespace every 'dfs.namenode.checkpoint.txns' transactions, regardless
  of whether 'dfs.namenode.checkpoint.period' has expired.
    操作次数
</description></property><property><name>dfs.namenode.checkpoint.check.period</name><value>60</value><description>The SecondaryNameNode and CheckpointNode will poll the NameNode
  every 'dfs.namenode.checkpoint.check.period' seconds to query the number
  of uncheckpointed transactions. Support multiple time unit suffix(case insensitive),
  as described in dfs.heartbeat.interval.If no time unit is specified then
  seconds is assumed.
  每分钟检查操作次数
</description></property>

DataNode 工作机制

一个数据块在 DataNode 上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。

  1. DataNode启动后向NameNode注册,注册成功后周期性(默认6小时)的向NameNode 上报所有的块信息;
<!--DN向NN汇报当前解读信息的时间间隔,默认6小时--><property><name>dfs.blockreport.intervalMsec</name><value>21600000</value><description>Determines block reporting interval in milliseconds.</description></property><!--DN扫描自己节点块信息列表的时间,默认6小时--><property><name>dfs.datanode.directoryscan.interval</name><value>21600</value><description>Interval in seconds for Datanode to scan data directories and
  reconcile the difference between blocks in memory and on the disk.
  Support multiple time unit suffix(case insensitive), as described
  in dfs.heartbeat.interval.If no time unit is specified then seconds
  is assumed.
</description></property>
  1. 心跳是每3秒一次,心跳返回结果带有NameNode给该DataNode的命令(如复制块数据到另一台机器,或删除某个数据块)。如果超过10分钟没有收到某个DataNode的心跳,则认为该节点不可用。
  2. 集群运行中可以安全加入和退出一些机器。


数据完整性

DataNode 节点保证数据完整性的方法。

  1. 当 DataNode 读取 Block 的时候,它会计算 CheckSum。
  2. 如果计算后的 CheckSum,与 Block 创建时值不一样,说明 Block 已经损坏。
  3. Client 读取其他 DataNode 上的 Block。
  4. 常见的校验算法crc (32) , md5(128), shal ( 160)。
  5. DataNode 在其文件创建后周期验证 CheckSum。


掉线时限参数设置

  1. DataNode 进程死亡或者网络故障造成DataNode无法与NameNode通信
  2. NameNode 不会立即把该节点判定为死亡,要经过一段时间,这段时间暂称作超时时长。
  3. HDFS默认的超时时长为10分钟+30秒。
  4. 如果定义超时时间为 TimeOut,则超时时长的计算公式为:

TimeOut = 2*dfs.namenode.heartbeat.recheck-interval+10* dfs.heartbeat.interval

而默认的dfs.namenode.heartbeat.recheck-interval 大小为5分钟,dfs.heartbeat.interval默认为3秒。

<!----><property><name>dfs.namenode.heartbeat.recheck-interval</name><value>300000</value><description>    This time decides the interval to check for expired datanodes.
    With this value and dfs.heartbeat.interval, the interval of
    deciding the datanode is stale or not is also calculated.
    The unit of this configuration is millisecond.
</description></property><!----><property><name>dfs.heartbeat.interval</name><value>3</value><description>    Determines datanode heartbeat interval in seconds.
    Can use the following suffix (case insensitive):
    ms(millis), s(sec), m(min), h(hour), d(day)
    to specify the time (such as 2s, 2m, 1h, etc.).
    Or provide complete number in seconds (such as 30 for 30 seconds).
    If no time unit is specified then seconds is assumed.
</description></property>


问题

问题一

问题详情

Permission denied: user=dr.who, access=WRITE, inode=“/“:root:supergroup:drwxr-xr-x

解决方案

hadoop fs -chmod777 /
目录
相关文章
|
2月前
|
分布式计算 Kubernetes Hadoop
大数据-82 Spark 集群模式启动、集群架构、集群管理器 Spark的HelloWorld + Hadoop + HDFS
大数据-82 Spark 集群模式启动、集群架构、集群管理器 Spark的HelloWorld + Hadoop + HDFS
167 6
|
2月前
|
SQL 分布式计算 监控
Hadoop-20 Flume 采集数据双写至本地+HDFS中 监控目录变化 3个Agent MemoryChannel Source对比
Hadoop-20 Flume 采集数据双写至本地+HDFS中 监控目录变化 3个Agent MemoryChannel Source对比
63 3
|
2月前
|
SQL 分布式计算 关系型数据库
Hadoop-24 Sqoop迁移 MySQL到Hive 与 Hive到MySQL SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-24 Sqoop迁移 MySQL到Hive 与 Hive到MySQL SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
90 0
|
2月前
|
SQL 分布式计算 关系型数据库
Hadoop-23 Sqoop 数据MySQL到HDFS(部分) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-23 Sqoop 数据MySQL到HDFS(部分) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
41 0
|
2月前
|
SQL 分布式计算 关系型数据库
Hadoop-22 Sqoop 数据MySQL到HDFS(全量) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-22 Sqoop 数据MySQL到HDFS(全量) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
51 0
|
分布式计算 应用服务中间件 Docker
Hadoop HDFS分布式文件系统Docker版
一、Hadoop文件系统HDFS 构建单节点的伪分布式HDFS 构建4个节点的HDFS分布式系统 nameNode secondnameNode datanode1 datanode2 其中 datanode2动态节点,在HDFS系统运行时,==动态加入==。
2627 0
|
2月前
|
分布式计算 资源调度 Hadoop
大数据-80 Spark 简要概述 系统架构 部署模式 与Hadoop MapReduce对比
大数据-80 Spark 简要概述 系统架构 部署模式 与Hadoop MapReduce对比
68 2
|
28天前
|
存储 分布式计算 Hadoop
数据湖技术:Hadoop与Spark在大数据处理中的协同作用
【10月更文挑战第27天】在大数据时代,数据湖技术凭借其灵活性和成本效益成为企业存储和分析大规模异构数据的首选。Hadoop和Spark作为数据湖技术的核心组件,通过HDFS存储数据和Spark进行高效计算,实现了数据处理的优化。本文探讨了Hadoop与Spark的最佳实践,包括数据存储、处理、安全和可视化等方面,展示了它们在实际应用中的协同效应。
88 2
|
29天前
|
存储 分布式计算 Hadoop
数据湖技术:Hadoop与Spark在大数据处理中的协同作用
【10月更文挑战第26天】本文详细探讨了Hadoop与Spark在大数据处理中的协同作用,通过具体案例展示了两者的最佳实践。Hadoop的HDFS和MapReduce负责数据存储和预处理,确保高可靠性和容错性;Spark则凭借其高性能和丰富的API,进行深度分析和机器学习,实现高效的批处理和实时处理。
65 1
|
2月前
|
分布式计算 Hadoop 大数据
大数据体系知识学习(一):PySpark和Hadoop环境的搭建与测试
这篇文章是关于大数据体系知识学习的,主要介绍了Apache Spark的基本概念、特点、组件,以及如何安装配置Java、PySpark和Hadoop环境。文章还提供了详细的安装步骤和测试代码,帮助读者搭建和测试大数据环境。
61 1