当前位置:   article > 正文

[大数据]二、Hadoop-HDFS

[大数据]二、Hadoop-HDFS

1. HDFS概述

1.1 HDFS产出背景定义

1)HDFS产生背景

随着数据量越来越大,在一个文件系统存不下所有的数据,那么就分配到更多的文件系统管理的磁盘中,但是不方便管理和维护,需要一种系统来管理多台机器上的文件,这就是分布式文件管理系统HDFS只是分布式文件管理系统中的一种。

2)HDFS定义

HDFSHadoop Distributed File System),它是一个文件系统,用于存储文件,通过目录树来定位文件;其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器有各自的角色。HDFS的使用场景:适合一次写入,多次读出的场景。一个文件经过创建、写入和关闭之后就不需要改变。

HDFS 最初是作为 Apache Hadoop 项目的一部分开发的。它被设计用来有效地存储和管理大规模数据集,并具有高度的容错性可伸缩性。以下是关于HDFS的一些关键特点和定义:

(1)分布式存储:HDFS将大文件划分为多个数据块,并在集群中的多台服务器上存储这些数据块的副本。这种方式可以实现数据的分布式存储和处理,提高了数据访问的速度和吞吐量。

(2)容错性:HDFS具有高度的容错性,通过存储数据块的冗余副本来应对服务器故障。如果某个节点出现故障,HDFS能够自动在其他节点上重新复制数据块,确保数据完整性和可靠性。

(3)扩展性:HDFS可以很容易地扩展以适应不断增长的数据量。通过添加新的节点来扩展存储容量和计算能力,HDFS可以无缝地处理大规模数据集,并在需要时灵活地增加服务器数量。

(4)数据局部性:HDFS利用数据局部性原则来提高性能,即将计算和数据尽可能地放置在相同的节点上(机架感知),减少数据传输的开销,提高数据处理效率。

(5)适用于大数据:HDFS是为存储和处理大数据而设计的,可以有效地处理海量数据,并提供高可靠性和高吞吐量的数据存储解决方案。

总的来说,HDFS是一种专为大规模数据处理而设计的分布式文件系统,具有容错性、可伸缩性和高性能的特点,适用于处理需要大数据存储和分析的场景。

1.2 HDFS的优缺点

HDFS(Hadoop Distributed File System)是 Apache Hadoop 生态系统中的一部分,用于存储大规模数据集并提供高可靠性、高性能的分布式存储解决方案。以下是 HDFS 的优缺点:

优点:
(1)容量扩展性(Scalability):HDFS 可以轻松扩展以处理大量数据。它支持横向扩展,可以在集群中添加更多的节点来扩大存储容量和处理能力。

(2)高容错性(Fault Tolerance):HDFS 提供了高度的容错性,通过数据复制和块的多副本存储在不同节点上,以应对硬件故障和节点失效。

(3)高性能(High Performance):HDFS 允许并行读/写数据,适用于大规模数据处理任务。数据在集群中分布存储和处理,实现了高速数据访问。

在分布式系统中,"并行"和"并发"是两个相关但不同的概念。在Hadoop Distributed File System(HDFS)中,它确实支持并行读写操作,这与支持并发读写的概念有所不同。

- 并行读写:并行读写涉及同时从多个不同的位置读取或写入数据。在HDFS中,多个数据节点可以同时处理读写请求,从而提高数据传输速度和系统性能。这种并行处理方式有助于加快大规模数据的读取和写入操作。

- 并发读写:并发读写指的是同时执行多个读写操作,可能针对同一个文件或数据块。在传统的文件系统中,往往需要额外的控制机制来确保并发读写的正确性,避免数据损坏或冲突。然而,HDFS设计时更侧重于大文件、批处理等工作负载,因此通常情况下并不支持对同一数据块的并发写操作。

在HDFS中,虽然支持多个客户端同时进行读写操作(并行读写),但对于同一数据块的写操作通常是排他的,即一次只能有一个客户端进行写入操作。这是因为HDFS采用了一种写一次、多次读取的设计模式(Write Once, Read Many),强调数据的高可靠性、持久性和一致性。

因此,HDFS在特定情况下支持并行读写,但不是指对同一数据块的并发写。对于同一数据块的写入会采用一些机制确保数据的一致性,例如副本机制和写入锁等。

(4)简易扩展性(Ease of Scalability):HDFS 的扩展性使得添加和移除节点相对容易,无需中断服务,对系统运行和维护具有较高的灵活性。

(5)数据本地性(Data Locality):HDFS 支持数据本地性,即处理数据的节点通常也存储着相应的数据块,减少了数据传输的开销,有助于提高性能。

(6)适合处理大数据:

        - 数据规模:能够处理数据规模达到GB、TB甚至PB级别的数据量;

        - 文件规模:能够处理百万规模以上的文件数量,数量相当之大

(7)低成本:可以构建在廉价服务器上,通过多副本机制,提高可靠性。

缺点:
(1)小文件问题(Small Files Problem):HDFS 不太适合存储大量小文件,因为每个文件的元数据开销较大,可能导致资源浪费和性能下降。

(2)实时性(Real-time Performance):HDFS 设计的初衷是处理大规模批处理任务,对于需要低延迟和实时性的应用不是最佳选择,如毫秒级的存储数据是做不到的。

(3)复杂性(Complexity):配置和管理 HDFS 集群可能需要一定的专业知识和经验。对于小型部署来说可能会显得过于繁琐和复杂。

(4)不适合小规模数据(Not Suitable for Small Data):对于小规模数据集来说,引入 HDFS 的开销可能会超过其带来的好处,不适合在这种情况下使用。

(5)不支持并发写入、文件随机修改

        - 一个文件只能有一个写,不允许多个线程同时写;

        - 仅支持数据 append(追加写),不支持文件的随机修改,如果要实现随机修改,需要客户端代码实现,先将随机插入位置的文件后面的数据拷贝一份,加入新数据,然后再将数据追加回去。

总体而言,HDFS 是一种适用于大规模数据存储和分析的分布式文件系统,具有众多优点但也需注意缺点,并根据应用需求和实际场景做出合适的选择。

1.3 HDFS组成

(1)NameNode(NN):元数据空间管理者

        - 管理HDFS名称空间(NameSpace)

        - 配置副本策略

        - 管理数据块(Block)映射信息

        - 处理客户端读写请求

(2)DataNode(DN):NameNode下达命令,DataNode执行实际的操作

        - 数据存储:DataNode 负责在本地文件系统存储数据块,将数据块写入磁盘并处理读取请求。HDFS 将大文件分成多个数据块,并在不同的 DataNode 上复制这些数据块,以实现数据的高可靠性和容错性。

        - 数据复制和块报告:DataNode 负责处理数据块的复制操作。它会周期性地向 NameNode 发送块报告(Block Report),告知 NameNode 所管理的数据块的信息,包括哪些数据块存储在自己所在的节点上。

        - 数据块复制的执行和处理:当某个数据块的副本数低于预定义的复制因子时(通常是3),DataNode 负责向其他节点复制数据块,以维持数据的冗余性和可靠性。

        - 数据块的定期检查与复制:DataNode 负责监视和维护节点上存储的数据块的完整性。它会定期检查数据块的状态,并确保数据块复制的数量符合 HDFS 的副本因子要求。

        - 接受客户端的读写请求:DataNode 会处理客户端的读取和写入请求。当客户端需要读取数据时,DataNode 会返回对应的数据块;当客户端需要写入数据时,DataNode 会接收并存储数据块。

总的来说,DataNode 是 HDFS 中负责存储数据的节点,通过协同工作,DataNode、NameNode 和客户端共同构成了 HDFS 分布式存储系统,实现了数据在集群环境下的高可靠性、容错性和可扩展性。

(3)Client:客户端

        - 文件切分,文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行上传;

        - 与NameNode交互,获取文件的位置信息;

        - 与DataNode交互,读取或写入数据;

        - Client提供命令管理HDFS,比如NameNode的格式化等;

        - Client 通过命令访问HDFS,比如对HDFS增删查改操作。

(4)SecondaryNameNode:并非NameNode的热备。当NameNode挂掉的时候,它不会替换NameNode提供服务。

        - 辅助NameNode,分担其工作量,比如定期合并Fsimage和Edits,并推送给NameNode;

        - 在紧急情况下,可以辅助恢复NameNode。

(5)StandbyNameNode:在HDFS-HA配置中的一部分        

        - Standby NameNode 是 Hadoop 高可用性(High Availability)部署的一部分,旨在防止单点故障。它与主 NameNode 处于热备份状态,即时准备接管主 NameNode 的工作。

        - 当主 NameNode 发生故障时,StandbyNameNode 可以快速接管服务,确保 HDFS 的正常运行,提高系统的可靠性。

        - Standby NameNode 会与主 NameNode保持同步,实时复制元数据变更,以确保在切换时数据一致性。

        - StandbyNameNode 在 HA 环境中会定期从主 NameNode 处复制编辑日志和镜像文件,合并这些日志并生成新的镜像文件,以保证在主 NameNode发生故障时可以快速地恢复元数据并启动为新的主 NameNode。

        - StandbyNameNode 也会周期性地检查主 NameNode 的健康状态,确保主 NameNode的正常运行。如果StandbyNameNode 检测到主 NameNode出现故障,它会触发自动故障转移并接管为新的主 NameNode,保证 HDFS 的高可用性和持久性。

1.4 HDFS文件块大小

HDFS 中的文件在物理上是分块存储(Block),块的大小可以通过配置参数(dfs.blocksize)来规定,默认的大小在Hadoop2.x  和Hadoop3.x 版本中是128MB,Hadoop1.x 版本是64MB。

Q:为什么是128MB的块大小

(1)集群中的block位置信息存储在NameNode中(内存中)

(2)假设寻址时间为10ms,即查找目标block的时间为10ms;

(3)寻址时间为传输时间的 1% 时,系统则为最佳状态(专家结论),因此传输时间=10ms/0.01=1s

(4)目前普通机械硬盘(HDD)的传输速率大致在100 MB/s到200 MB/s之间;

(5)因此 block=100MB/s * 1s = 100MB 默认设置为100MB可以减少寻址开销。

Q:为什么块的大小不能设置太小,也不能设置太大,我的集群应该根据什么来设置块大小

(1)HDFS的块设置太小,会增加寻址时间,即程序找寻块的开始位置比较耗时,因为块设置太小,会被分成多个块,元数据信息会增加;

(2)如果块设置太大,从磁盘传输数据的时间会明显大于查找这个块开始位置的时间。程序处理这块数据时,会显得比较慢。

因此:HDFS块的大小设置主要取决于磁盘传输速率。(磁盘的传输速率用fio等工具测试一下)

2. HDFS shell操作

2.1 基本语法

hadoop fs -具体命令 或者 hdfs dfs -具体命令。

2.2 命令大全

  1. [seven@hadoop111 logs]$ hadoop fs
  2. Usage: hadoop fs [generic options]
  3. [-appendToFile [-n] <localsrc> ... <dst>]
  4. [-cat [-ignoreCrc] <src> ...]
  5. [-checksum [-v] <src> ...]
  6. [-chgrp [-R] GROUP PATH...]
  7. [-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
  8. [-chown [-R] [OWNER][:[GROUP]] PATH...]
  9. [-concat <target path> <src path> <src path> ...]
  10. [-copyFromLocal [-f] [-p] [-l] [-d] [-t <thread count>] [-q <thread pool queue size>] <localsrc> ... <dst>]
  11. [-copyToLocal [-f] [-p] [-crc] [-ignoreCrc] [-t <thread count>] [-q <thread pool queue size>] <src> ... <localdst>]
  12. [-count [-q] [-h] [-v] [-t [<storage type>]] [-u] [-x] [-e] [-s] <path> ...]
  13. [-cp [-f] [-p | -p[topax]] [-d] [-t <thread count>] [-q <thread pool queue size>] <src> ... <dst>]
  14. [-createSnapshot <snapshotDir> [<snapshotName>]]
  15. [-deleteSnapshot <snapshotDir> <snapshotName>]
  16. [-df [-h] [<path> ...]]
  17. [-du [-s] [-h] [-v] [-x] <path> ...]
  18. [-expunge [-immediate] [-fs <path>]]
  19. [-find <path> ... <expression> ...]
  20. [-get [-f] [-p] [-crc] [-ignoreCrc] [-t <thread count>] [-q <thread pool queue size>] <src> ... <localdst>]
  21. [-getfacl [-R] <path>]
  22. [-getfattr [-R] {-n name | -d} [-e en] <path>]
  23. [-getmerge [-nl] [-skip-empty-file] <src> <localdst>]
  24. [-head <file>]
  25. [-help [cmd ...]]
  26. [-ls [-C] [-d] [-h] [-q] [-R] [-t] [-S] [-r] [-u] [-e] [<path> ...]]
  27. [-mkdir [-p] <path> ...]
  28. [-moveFromLocal [-f] [-p] [-l] [-d] <localsrc> ... <dst>]
  29. [-moveToLocal <src> <localdst>]
  30. [-mv <src> ... <dst>]
  31. [-put [-f] [-p] [-l] [-d] [-t <thread count>] [-q <thread pool queue size>] <localsrc> ... <dst>]
  32. [-renameSnapshot <snapshotDir> <oldName> <newName>]
  33. [-rm [-f] [-r|-R] [-skipTrash] [-safely] <src> ...]
  34. [-rmdir [--ignore-fail-on-non-empty] <dir> ...]
  35. [-setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>]|[--set <acl_spec> <path>]]
  36. [-setfattr {-n name [-v value] | -x name} <path>]
  37. [-setrep [-R] [-w] <rep> <path> ...]
  38. [-stat [format] <path> ...]
  39. [-tail [-f] [-s <sleep interval>] <file>]
  40. [-test -[defswrz] <path>]
  41. [-text [-ignoreCrc] <src> ...]
  42. [-touch [-a] [-m] [-t TIMESTAMP (yyyyMMdd:HHmmss) ] [-c] <path> ...]
  43. [-touchz <path> ...]
  44. [-truncate [-w] <length> <path> ...]
  45. [-usage [cmd ...]]
  46. Generic options supported are:
  47. -conf <configuration file> specify an application configuration file
  48. -D <property=value> define a value for a given property
  49. -fs <file:///|hdfs://namenode:port> specify default filesystem URL to use, overrides 'fs.defaultFS' property from configurations.
  50. -jt <local|resourcemanager:port> specify a ResourceManager
  51. -files <file1,...> specify a comma-separated list of files to be copied to the map reduce cluster
  52. -libjars <jar1,...> specify a comma-separated list of jar files to be included in the classpath
  53. -archives <archive1,...> specify a comma-separated list of archives to be unarchived on the compute machines
  54. The general command line syntax is:
  55. command [genericOptions] [commandOptions]

2.3 常用命令

2.3.1 准备工作

(1)启动Hadoop集群

(2)-help:输出这个命令的帮助文档        

  1. [seven@hadoop111 logs]$ hadoop fs -help rm
  2. -rm [-f] [-r|-R] [-skipTrash] [-safely] <src> ... :
  3. Delete all files that match the specified file pattern. Equivalent to the Unix
  4. command "rm <src>"
  5. -f If the file does not exist, do not display a diagnostic message or
  6. modify the exit status to reflect an error.
  7. -[rR] Recursively deletes directories.
  8. -skipTrash option bypasses trash, if enabled, and immediately deletes <src>.
  9. -safely option requires safety confirmation, if enabled, requires
  10. confirmation before deleting large directory with more than
  11. <hadoop.shell.delete.limit.num.files> files. Delay is expected when
  12. walking over large directory recursively to count the number of
  13. files to be deleted before the confirmation.
  14. [seven@hadoop111 logs]$

2.3.2 上传

(1)-moveFromLocal:从本地剪切粘贴到HDFS

(2)-copyFromLocal:从本地文件系统中拷贝文件到HDFS路径去

(3)-put:等同于copyFromLocal,更习惯用put

(4)-appendToFile:追加一个文件到已经存在的文件末尾

        hadoop fs -appendToFile xx_2.txt /xx_1.txt

2.3.3 下载

(1)-copyToLocal:从HDFS拷贝到本地

(2)-get:等同于copyToLocal,生产环境更习惯用get
(3)-moveToLocal <src> <localdst>:从HDFS剪切到本地文件系统

2.3.4 直接操作文件

(1)-rm -r:递归删除目录目录里面内容

(2)-du:统计文件夹的大小信息        

  1. []$ hadoop fs -du -s -h /jinguo
  2. 27 81 /jinguo
  3. []$ hadoop fs -du -h /jinguo
  4. 14 42 /jinguo/shuguo.txt
  5. 7 21 /jinguo/weiguo.txt
  6. 6 18 /jinguo/wuguo.tx

        说明:-s 查看的信息:27表示文件大小81表示 27*3 个副本;/jinguo表示查看的目录

 (3)-setrep:设置HDFS中文件的副本数量

        hadoop fs -setrep 10 /jinguo/shuguo.txt

        说明:这里设置的副本数只是记录在NameNode的元数据中,是否真的会有这么多副本,还得看DataNode的数量。因为目前只有3台设备,最多也就3个副本,只有节点数的增加到10台时,副本数才能达到10。

3. HDFS API操作

3.1 Windows客户端环境准备

(1)解压Hadoop安装包到本地文件系统

        G:\Bigdata\bigdata_client\hadoop-3.3.6

(2)下载winutils

        https://github.com/cdarlint/winutils

        双击:winutils.exe

        如果一闪而过,表示系统正常,如果出现缺少某个 dll 文件,则需要修复系统。

(3)配置HADOOP_HOME环境变量

(4)配置Path环境变量。

        注意:如果环境变量不起作用,可以重启电脑试试。

(5)在IDEA中创建一个Maven工程,并导入相应的依赖坐标+日志

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.apache.hadoop</groupId>
  4. <artifactId>hadoop-client</artifactId>
  5. <version>3.3.6</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>junit</groupId>
  9. <artifactId>junit</artifactId>
  10. <version>4.13.1</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.slf4j</groupId>
  14. <artifactId>slf4j-log4j12</artifactId>
  15. <version>1.7.30</version>
  16. </dependency>
  17. </dependencies>

        在项目的src/main/resources目录下,新建一个文件,命名为“log4j.properties”,在文件中填入以下内容:

  1. log4j.rootLogger=INFO, stdout
  2. log4j.appender.stdout=org.apache.log4j.ConsoleAppender
  3. log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
  4. log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
  5. log4j.appender.logfile=org.apache.log4j.FileAppender
  6. log4j.appender.logfile.File=target/hadoop.log
  7. log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
  8. log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n

(6)创建HdfsClient类,并完成连接测试

  1. import org.apache.hadoop.conf.Configuration;
  2. import org.apache.hadoop.fs.FileSystem;
  3. import org.apache.hadoop.fs.Path;
  4. import org.junit.Test;
  5. import java.io.IOException;
  6. import java.net.URI;
  7. import java.net.URISyntaxException;
  8. /**
  9. * ClassName: HdfsClient
  10. * Package: com.huaweicloud.hadoop_client
  11. *
  12. * @Author: Seven
  13. * @Create: 2024/5/11 23:52
  14. * @Version: 1.0
  15. * @Description: HDFS API 测试
  16. */
  17. public class HdfsClient {
  18. @Test
  19. public void testMkdirs() throws IOException, URISyntaxException, InterruptedException {
  20. // 1 获取文件系统
  21. Configuration configuration = new Configuration();
  22. FileSystem fs = FileSystem.get(new URI("hdfs://hadoop112:8020"), configuration);
  23. //FileSystem fs = FileSystem.get(new URI("hdfs://hadoop112:8020"), configuration,"seven");
  24. // 2 创建目录
  25. fs.mkdirs(new Path("/xiyou/huaguoshan/"));
  26. // 3 关闭资源
  27. fs.close();
  28. }
  29. }

注意:客户端去操作HDFS时,是有一个用户身份的。默认情况下,HDFS客户端API会从采用Windows默认用户访问HDFS,会报权限异常错误。所以在访问HDFS时,一定要配置用户(seven)。

3.2 HDFS的API案例

参数优先级排序:(1)客户端代码中设置的值  ->(2)ClassPath下的用户自定义配置文件 ->(3)然后是服务器的自定义配置(xxx-site.xml) ->(4)服务器的默认配置(xxx-default.xml)

3.2.1 HDFS文件上传

  1. @Test
  2. public void testCopyFromLocalFile() throws URISyntaxException, IOException, InterruptedException {
  3. // 1 获取文件系统
  4. Configuration conf = new Configuration();
  5. URI uri = new URI("hdfs://hadoop112:8020");
  6. FileSystem fs = FileSystem.get(uri, conf, "seven");
  7. // 2 上传文件
  8. Path file_abs_path = new Path("G:/Bigdata/1.hadoop/datas/xunwukong.txt");
  9. Path dest_path = new Path("/xiyou/huaguoshan");
  10. fs.copyFromLocalFile(file_abs_path, dest_path);
  11. // 3 关闭资源。
  12. fs.close();
  13. }

3.2.2 HDFS文件下载

  1. @Test
  2. public void testCopyToLocalFile() throws IOException, URISyntaxException, InterruptedException {
  3. Configuration conf = new Configuration();
  4. FileSystem fs = FileSystem.get(new URI("hdfs://hadoop112:8020"), conf, "seven");
  5. // 执行下载:
  6. // boolean delSrc 是否将原文件删除
  7. // Path src 要下载的文件路径,到文件名
  8. // Path dst 指的是将要下载到的路径
  9. // boolean useRawLocalFileSystem 是否开启文件校验。
  10. fs.copyToLocalFile(false, new Path("/xiyou/huaguoshan/xunwukong.txt"),
  11. new Path("G:/Bigdata/1.hadoop/datas/xunwukong2.txt"), true);
  12. fs.close();
  13. }

3.2.3 HDFS文件更名和移动

  1. @Test
  2. public void testRename() throws URISyntaxException, IOException, InterruptedException {
  3. Configuration conf = new Configuration();
  4. FileSystem fs = FileSystem.get(new URI("hdfs://hadoop112:8020"), conf, "seven");
  5. fs.rename(new Path("/xiyou/huaguoshan/xunwukong.txt"),
  6. new Path("/xiyou/huaguoshan/meihouwang.txt"));
  7. fs.close();
  8. }

3.2.4 HDFS删除文件和目录

  1. @Test
  2. public void testDelete() throws URISyntaxException, IOException, InterruptedException {
  3. Configuration conf = new Configuration();
  4. FileSystem fs = FileSystem.get(new URI("hdfs://hadoop112:8020"), conf, "seven");
  5. fs.delete(new Path("/xiyou"), true);
  6. fs.close();
  7. }

3.2.5 文件详情查看

  1. /**
  2. * 查看文件名称、权限、长度、块信息等
  3. */
  4. @Test
  5. public void testListFiles() throws URISyntaxException, IOException, InterruptedException {
  6. Configuration conf = new Configuration();
  7. FileSystem fs = FileSystem.get(new URI("hdfs://hadoop112:8020"), conf, "seven");
  8. RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/xiyou"), true);
  9. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  10. while (listFiles.hasNext()){
  11. LocatedFileStatus fileStatus = listFiles.next();
  12. System.out.println("========== " + fileStatus.getPath() + " =========");
  13. System.out.println("Permission: " + fileStatus.getPermission());
  14. System.out.println("Owner: " + fileStatus.getOwner());
  15. System.out.println("Group: " + fileStatus.getGroup());
  16. long ts = fileStatus.getModificationTime();
  17. String formattedDate = sdf.format(ts);
  18. System.out.println("Mtime: " + formattedDate);
  19. System.out.println("Replications: " + fileStatus.getReplication());
  20. System.out.println("BlockSize: " + fileStatus.getBlockSize());
  21. System.out.println("Locations: " + Arrays.toString(fileStatus.getBlockLocations()));
  22. System.out.println("Name: " + fileStatus.getPath().getName());
  23. }
  24. }

========== hdfs://hadoop112:8020/xiyou/huaguoshan/meihouwang.txt =========
Permission: rw-r--r--
Owner: seven
Group: supergroup
Mtime: 2024-05-12 00:44:18
Replications: 3
BlockSize: 134217728
Locations: [0,54,hadoop112,hadoop111,hadoop113]
Name: meihouwang.txt

其中:Locations: [0,54,hadoop112,hadoop111,hadoop113] 

        0:表示数据块在文件中的起始偏移量

        54:表示数据块的长度

        hadoop112,hadoop111,hadoop113:代表存储数据块的节点,即这些数据节点存储着副本。

3.2.6 文件和文件夹判断

  1. @Test
  2. public void testStatus() throws IOException, URISyntaxException, InterruptedException {
  3. Configuration conf = new Configuration();
  4. FileSystem fs = FileSystem.get(new URI("hdfs://hadoop112:8020"), conf, "seven");
  5. FileStatus[] fileStatuses = fs.listStatus(new Path("/xiyou"));
  6. for(FileStatus fileStatus: fileStatuses){
  7. if (fileStatus.isFile()){
  8. System.out.println("f: " + fileStatus.getPath().getName());
  9. }else {
  10. System.out.println("d: " + fileStatus.getPath().getName());
  11. }
  12. }
  13. fs.close();
  14. }

4. HDFS 读写流程

4.1 HDFS写数据流程

4.1.1 剖析文件写入

(1)客户端通过DistributedFileSystem模块向NameNode请求上传文件,NameNode检查目标文件是否存在,父目录是否存在。

(2)NameNode返回是否可以上传。

(3)客户端请求第一个Block上传到哪几个DataNode服务器上。

(4)NameNode返回三个DataNode节点,分别是dn1,dn2,dn3.

(5)客户端通过FSDataOutputStream模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成。

(6)dn1、dn2、dn3逐级应答客户端。

(7)客户端开始往dn1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位,dn1收到一个Packet就会传给dn2,dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答

(8)当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器。(重复执行3-7步)。

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

        在HDFS写数据过程中,NameNode会选择距离待上传数据最近距离的DataNode接收数据。那么这个最近距离怎么计算呢?

        节点距离:两个节点到达最近的共同父节点的距离之和

4.2 HDFS读数据流程

(1)客户端通过DistributedFileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址。

(2)挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。

(3)DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)。

(4)客户端以Packet为单位接收,先在本地缓存,然后写入目标文件。

5. NameNode

5.1 NameNode和2NN的工作机制

        思考:NameNode中的元数据是存储在哪里的?

        首先,我们做个假设,如果存储在NameNode节点的磁盘中,因为经常需要进行随机访问,还有响应客户请求,必然是效率过低。因此,元数据需要存放在内存中。但如果只存在内存中,一旦断电,元数据丢失,整个集群就无法工作了。因此产生在磁盘中备份元数据的FsImage。

        这样又会带来新的问题,当在内存中的元数据更新时,如果同时更新FsImage,就会导致效率过低,但如果不更新,就会发生一致性问题,一旦NameNode节点断电,就会产生数据丢失。因此,引入Edits文件只进行追加操作,效率很高。每当元数据有更新或者添加元数据时,修改内存中的元数据并追加到Edits中。这样,一旦NameNode节点断电,可以通过FsImage和Edits的合并,合成元数据。

        但是,如果长时间添加数据到Edits中,会导致该文件数据过大,效率降低,而且一旦断电,恢复元数据需要的时间过长。因此,需要定期进行FsImage和Edits的合并,如果这个操作由NameNode节点完成,又会效率过低。因此,引入一个新的节点SecondaryNamenode,专门用于FsImage和Edits的合并。

1)第一阶段:NameNode启动

(1)第一次启动NameNode格式化后,创建Fsimage和Edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存。

(2)客户端对元数据进行增删改的请求。

(3)NameNode记录操作日志,更新滚动日志。

2)第二阶段:Secondary NameNode工作

(1)Secondary NameNode询问NameNode是否需要CheckPoint。直接带回NameNode是否检查结果。NameNode在内存中对元数据进行增删改。

(2)Secondary NameNode请求执行CheckPoint。

(3)NameNode滚动正在写的Edits日志。

(4)将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode。

(5)Secondary NameNode加载编辑日志和镜像文件到内存,并合并。

(6)生成新的镜像文件fsimage.chkpoint。

(7)拷贝fsimage.chkpoint到NameNode。

(8)NameNode将fsimage.chkpoint重新命名成fsimage。

5.2 Fsimage 和 Edits 解析

       NameNode被格式化之后,将在NameNode指的的目录中产生Fsimage文件:

        

        (1)fsimage文件:HDFS文件系统元数据的一个永久性的检查点,其中包含HDFS文件系统的所有目录和文件inode的序列化信息。

        (2)edits文件:存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先会被记录到edits文件中。

        (3)seen_txid:该文件保存的是一个数字,就是最后一个edits 的数字。

        (4)VERSION:版本信息,每次NameNode启动的时候都会将fsimage文件读入内存,加载edits里面的更新操作,保证内存中的元数据信息是最新的、同步的,可以看成NameNode启动的时候就将fsimage和edits文件进行了合并。

1)oiv 查看fsimage文件

        (1)查看ovi 和 oev 命令:hdfs 回车,检查输出的内容

                oev                  apply the offline edits viewer to an edits file
                oiv                  apply the offline fsimage viewer to an fsimage

        (2)基本语法:

                hdfs oiv -p 文件类型 -i 镜像文件 -o 转换后文件输出路径

                hdfs oiv -p XML -i fsimage_0000000000025 -o ./fsimage.xml

2)oev 查看edits 文件内容

        (1)基本语法:

                hdfs oev -p 文件类型 -i 编辑日志 -o 转换后文件输出路径

                hdfs oev -p XML -i edits_0000000000000008577-0000000000000008578 -o ./edits.xml

5.3 Checkpoint 时间设置

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

  1. [hdfs-default.xml]
  2. <property>
  3. <name>dfs.namenode.checkpoint.period</name>
  4. <value>3600s</value>
  5. </property>

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

  1. <property>
  2. <name>dfs.namenode.checkpoint.txns</name>
  3. <value>1000000</value>
  4. <description>操作动作次数</description>
  5. </property>
  6. <property>
  7. <name>dfs.namenode.checkpoint.check.period</name>
  8. <value>60s</value>
  9. <description> 1分钟检查一次操作次数</description>
  10. </property>

6. DataNode

6.1 DataNode工作机制

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

(2)DataNode启动后向NameNode注册,通过后,周期性(6小时)的向NameNode上报所有的块信息。

        DN向NN汇报当前解读信息的时间间隔,默认6小时;

  1. <property>
  2. <name>dfs.blockreport.intervalMsec</name>
  3. <value>21600000</value>
  4. <description>Determines block reporting interval in milliseconds.</description>
  5. </property>

        DN扫描自己节点块信息列表的时间,默认6小时

  1. <property>
  2. <name>dfs.datanode.directoryscan.interval</name>
  3. <value>21600s</value>
  4. <description>Interval in seconds for Datanode to scan data directories and reconcile the difference between blocks in memory and on the disk.
  5. Support multiple time unit suffix(case insensitive), as described
  6. in dfs.heartbeat.interval.
  7. </description>
  8. </property>

(3)心跳是每3秒一次,心跳返回结果带有NameNode给该DataNode的命令如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟没有收到某个DataNode的心跳,则认为该节点不可用。

(4)集群运行中可以安全加入和退出一些机器。

6.2 数据完整性

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

(1)当DataNode读取Block的时候,它会计算CheckSum。

(2)如果计算后的CheckSum,与Block创建时值不一样,说明Block已经损坏。

(3)Client读取其他DataNode上的Block。

(4)常见的校验算法crc(32),md5(128),sha1(160)

(5)DataNode在其文件创建后周期验证CheckSum。

6.3 掉线时限参数设置

需要注意的是hdfs-site.xml 配置文件中的heartbeat.recheck.interval的单位为毫秒,dfs.heartbeat.interval的单位为

  1. <property>
  2. <name>dfs.namenode.heartbeat.recheck-interval</name>
  3. <value>300000</value>
  4. </property>
  5. <property>
  6. <name>dfs.heartbeat.interval</name>
  7. <value>3</value>
  8. </property>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/608980
推荐阅读
相关标签
  

闽ICP备14008679号