Hadoop之HDFS实用篇

    科技2022-08-17  107

    系列文章目录

    Hadoop了解篇 Hadoop之HDFS Hadoop之MapReduce Hadoop之Yarn Hadoop之优化&新特性


    文章目录

    系列文章目录前言一、HDFS是什么?1.HDFS2.应用场景3.HDFS特点 二、HDFS组成1.构架2.HDFS文件块(Block)大小的如何确定?***why?***3.HDFS的Shell操作 二、HDFS客户端操作1.HDFS客户端环境准备2.HDFS的API操作 二、HDFS读写数据流程1.HDFS写数据流程1.1 客户端数据先发送给哪个DataNode呢?是随机的吗?1.2 副本储存的节点是如何选择的呢?1.3 建立传输通道时,某一传输通道连接不上,怎么办?1.4 写数据时,某一传输通道连接不上,怎么办?2.HDFS读数据流程2.1 步骤4传输中断怎么办?2.2 blk_1、blk_2可以同时读吗? 三、NameNode和SecondaryNameNode1.NameNode中的数据存储在哪里呢?2.Fsimage和Edits进步解析?3.Fsimage中为什么没有记录DataNode?4.CheckPoint时间设置5.Secondary NameNode中的元数据完整吗?6.集群安全模式 四、DataNode1.工作机制2.DataNode上数据损坏,怎么办?3.退役节点 总结


    前言

    当下数据量的爆发式增长,在一个操作系统中,我们很难存下所有数据,这时就需要将数据放在等多个操作系统的磁盘中。此时另一个难题就出来了,我们如何对多台电脑的磁盘进行管理呢?这个时候分布式文件管理系统就登场了。


    一、HDFS是什么?

    1.HDFS

    是一个文件系统,用于储存文件,通过目录树来定位文件 并且是分布式的,文件分布在多台服务器的磁盘中。

    2.应用场景

    适合一次写入,多次读出,不支持文件的修改。(内部维持多个副本,随机写的话,分布式数据一致性会受到挑战。而如果一定要保证实时的数据一致性,那么性能上的牺牲就会太大了。所以说,随机写不属于HDFS的适用场景。)

    3.HDFS特点

    优点:

    特点为何?高容错性内部维持多个副本,单一副本丢失,可自动恢复处理数据量大最大处理TB、PB级别的数据;处理百万规模的文件数量可在廉价机器上内部维持多个副本,单一副本丢失,可自动恢复

    缺点:

    特点为何?低延迟储存做不到多副本机制的弊端 ,毫秒级储存难以达到多小文件高效存储做不到会占用大量的NameNode的内存来储存文件元数据;小文件的寻址时间会超过读取时间并发写入,随机修改做不到一个文件只能一个写,不可以多线程同时写;仅支持数据的追加(Append)

    二、HDFS组成

    1.构架

    组件作用NameNode管理元数据、配置副本策略、管理Block映射信息、处理客户端读写请求DataNode存储实际的数据块、执行数据的读/写操作Client文件切分成Block然后上传 、与NameNode交互,获取文件位置信息、与DataNode交互,读取/写入数据、提供命令管理/操作HDFS,eg:对NameNode的格式化Secondory NameNode紧急情况下,可辅助恢复NameNode了,具体见后续

    2.HDFS文件块(Block)大小的如何确定?

    首先明白:HDFS上的文件在物理上是分块存储(Block),块的大小我们可以根据实际的生产环境通过配置参数(dfs blocksize)来设定。在老版本中默认大小为64M,新版本(2.X)中默认大小为128M。

    why?

    以从HDFS上下载一个文件为例:

    约定:寻址时间为传输时间的1%时,为最佳状态1.假设寻址时间为10ms,即查找目标Block的时间为10ms2.因此在最佳状态下,传输时间为10/0.01=1s3.而目前磁盘的传输速率普遍为100M/S4.1S * 100M/S = 100M5.最接近100M就是128M

    3.HDFS的Shell操作

    1)基本语法

    bin/hadoop fs 具体命令 or bin/hdfs dfs 具体命令

    2)常用命令实操 (1)上传

    -moveFromLocal:从本地剪切粘贴到HDFS上 hadoop fs -moveFromLocal ./helloworld.txt /input -copyFromLocal:从本地文件系统中拷贝文件到HDFS路径去 hadoop fs -copyFromLocal ./helloworld.txt /input -appendToFile:追加一个文件到已经存在的文件末尾 hadoop fs -appendToFile helloworld.txt /input/yilei.txt -put:等同于copyFromLocal hadoop fs -put ./helloworld.txt /input

    (2)下载

    -copyToLocal:从HDFS上拷贝到本地 hadoop fs -copyToLocal /input/helloworld.txt ./ -get:等同于copyToLocal hadoop fs -get ./helloworld.txt /input -getmerge:合并多个文件下载 hadoop fs -getmerge /user/yilei/bin/* ./helloworld.txt

    3)HDFS直接操作

    -ls:显示目录信息 hadoop fs -ls -mkdir:在HDFS上创建目录 hadoop fs -mkdir /sanguo/liubei.txt -cat:显示文件内容 hadoop fs -cat /sanguo/liubei.txt -cp :从HDFS的一个路径拷贝到HDFS的另一个路径 hadoop fs -cp /sanguo/liubei.txt /input/ -du:统计文件夹的大小信息 hadoop fs -du -s -h /sanguo 2.7k /sanguo -setrep:设置HDFS中的文件副本数 hadoop fs -setrep 10 /sanguo/liubei.txt

    二、HDFS客户端操作

    1.HDFS客户端环境准备

    1)下载Hadoop 2)配置Hadoop的环境变量 3)配置Path环境变量,重启电脑 4)创建Maven工程,并导入相应的依赖

    2.HDFS的API操作

    获取文件系统对象的方式一:(常用方式)

    public class HdfsClient{ @Test public void testMkdirs(){ //连接地址 UIR uri = new URI("hdfs://hadoop01:9820"); //创建配置文件对象 Configuration conf = new Configuration(); //1.文件系统对象 /* 参数一:NameNode的连接地址 参数二:配置文件对象 参数三:操作hdfs的用户 */ FileSystem fs = FileSystem.get(uri,conf,"yilei") //2.对应操作 System.out.println(fs); //3.关闭资源 fs.close(); } }

    获取文件系统对象的方式二: 注:需要在EditConfigurations中配置 VM options: -DHADOOP_USER_NAME=yilei

    public class HdfsClient{ @Test public void testMkdirs(){ //创建配置文件的对象 Configuration conf = new Configuration(); //通过配置文件配置NameNode的地址 conf.set("fs.defaultFS","hdfs://hadoop01:9820"); FileSystem fs = FileSystem.get(conf); //2.对应操作 System.out.println(fs); //3.关闭资源 fs.close(); } }

    客户端操作上传文件

    @Test public void test() throws IOException(){ /* 参数一:是否删除源文件 参数二:是否覆盖目标文件(目标文件已经存在的情况下) true:覆盖 false:不覆盖,但是目标文件存在的情况下会抛异常 参数三:源文件路径 参数四:目标文件路径 */ fs.copyFromLocalFile(true,true,new Path("D:\\tset\\aa.txt"),new Path("/")) }

    客户端操作下载文件

    @Test public void test1() throws IOException(){ /* 参数一:是否删除源文件 参数二:源文件路径 参数三:目标文件路径 参数四:是否使用RawLocalFileSystem false:会生成crc文件 true:不会生成crc文件 */ fs.copyToLocalFile(false,new Path("/aa.txt"),new Path("D://test"),true); }

    文件删除

    @Test public void test1() throws IOException(){ /* 参数一:要删除的文件或目录的路径 参数二:只对目录有效,如果是一个目录那么必须为true,如果文件就无所谓 */ fs.delete(new Path("/cc.txt"),true); }

    文件名更改

    @Test public void test1() throws IOException(){ /* 第一个参数 :源文件路径(文件修改名字前的路径) 第二个参数 :目标文件路径 (文件修改名字后的路径) */ fs.delete(new Path("/cc.txt"),new Path("aa.txt")); }

    查看文件详情

    @Test public void test1() throws IOException(){ /* 第一个参数 : 要遍历的目录路径 第二个参数 : 是否递归(是否查看子目录中的内容) */ RemoteIterator<LocatedFileStatus> fileStatus = fs.listFiles(new Path("/"), true); //是否有下一个元素 while(fileStatus.hasNext()){ System.out.println("===================文件信息================="); //获取一个元素 LocatedFileStatus file = fileStatus.next(); //获取文件的名称 System.out.println("文件名:" + file.getPath().getName()); System.out.println("副本数:" + file.getReplication()); System.out.println("-----------------块信息---------------------"); BlockLocation[] blockLocations = file.getBlockLocations(); System.out.println(Arrays.toString(blockLocations)); } }

    判断是文件还是目录

    @Test public void test2() throws IOException { FileStatus[] status = fs.listStatus(new Path("/")); for (FileStatus file : status) { if (file.isFile()){ System.out.println(file.getPath().getName() + "是一个文件"); }else if (file.isDirectory()){ System.out.println(file.getPath().getName() + "是一个目录"); } } }

    通过流向HDFS上传或下载文件 上传(fs为文件系统对象)

    @test public void test3()throws IOException{ //1.读 - 本地 FileInputStream fis = new FileInputStream("D:\\test\\aa.txt"); //2.写 - HDFS FSDataOutputStream os = fs.create(new Path("/aa.txt")); //3.一边读一遍写(文件对拷) //参数三:缓冲区大小 //参数四:对拷完毕是否关流 IOUtils.copyBytes(fis,os,3000,true); }

    下载(fs为文件系统对象)

    @test public void test4()throws IOException{ //1.读 - HDFS FSDataInputStream fis = fs.open(new Path("/aa.txt")); //2.写 - 本地 FileOutputStream fos = new FileOutputStream(new Path("d:\\test\\aa.txt")); //3.一边读一遍写(文件对拷) //参数三:缓冲区大小 //参数四:对拷完毕是否关流 IOUtils.copyBytes(fis,fos,3000,true); }

    二、HDFS读写数据流程

    1.HDFS写数据流程

    步骤详述1、客户端通过Distributed FileSystem模块向NameNode请求上传文件,NameNode请求上传文件,NameNode检查文件是否已存在,父目录是否存在2、NameNode返回是否上传3、客户端请求第一个Block上传到哪几个DataNode服务器上4、NameNode返回3个DataNode节点,分别为n1、n2、n35、客户端通过FSDataOutputStream模块请求n1上传数据,n1收到请求会继续调用n2,然后n2调用n3,将这个通信管道建立完成6、n1、n2、n3逐级应答客户端7、客户端开始往dn1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位(一个Packet为64K),dn1收到一个Packet就会传给dn2(同时会往本地磁盘写),dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答8、当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器(重复执行3-7步)

    1.1 客户端数据先发送给哪个DataNode呢?是随机的吗?

    答:不是随机,客户端会选择距离待上传数据最近的DataNode接收数据。

    那如何知道它的距离是最近呢?

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

    eg:Distance(/d1/r1/n0,/d1/r1/n0)=0 (统一节点上的进程) Distance(/d1/r2/n1,/d2/r4/n1)=6 (不同数据中心的节点)

    1.2 副本储存的节点是如何选择的呢?

    副本节点选择(Hadoop3.X)第一个副本:在client所处节点上,若客户端在集群外,随机选一个第二个副本:在另外一个机架的随机一个节点上第三个副本:在第二个副本所在机架的随机节点(不与第二副本所在节点相同)

    1.3 建立传输通道时,某一传输通道连接不上,怎么办?

    答:重新建立传输通道,此时就会跳过刚才连接失败的节点; 此时可能就会存在疑问,该案例中是不是就会少了一个副本,短期看是的; DataNode会定期向NameNode汇报块信息,此时NameNode一旦发现异常,会进行对应的修复,保证Datanode与NameNode的一致性。

    1.4 写数据时,某一传输通道连接不上,怎么办?

    答:会进行四次尝试,如果还是连接不上则跳过该节点,向其他节点传输

    2.HDFS读数据流程

    步骤详述1、客户端通过Distributed FileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件所在的DataNode地址2、挑选一台DataNode(就近原则,然后随机)服务器,请求下载数据3、DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)4、客户端以Packet为单位接收,先在本地缓存,然后写入目标文件

    2.1 步骤4传输中断怎么办?

    答:客户端会将读取到的不完整的数据进行清除,重新找一个节点下载blk_1;不存在断点下载。

    2.2 blk_1、blk_2可以同时读吗?

    答:可以,前提是两个客户端(可以并发读,不支持并发写),但是两个客户端读的是两份hello.txt。

    三、NameNode和SecondaryNameNode

    1.NameNode中的数据存储在哪里呢?

    假设在磁盘中,我们随机访问时效率会很低 假设在内存中,数据就很容易就丢失了 上面两个假设都不成立,除非上述两种情况同时并行,磁盘内存都存一份

    第一阶段:NameNode启动1、第一次启动NameNode格式化后,创建fsimage和edits文件。若不是第一次启动,直接加载编辑日志和镜像文件到内存2、客户端对元数据进行增删改的请求3、NameNode记录操作日志,更新滚动日志4、NameNode在内存中对元数据进行增删改 第二阶段 :Secondary NameNode工作1、Secondary NameNode询问NameNode是否需要CheckPoint。直接返回NameNode是否检查结果2、Secondary NameNode请求执行CheckPoint3、NameNode滚动正在写的Edits日志4、将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode5、Secondary NameNode加载编辑日志和镜像文件到内存,并合并6、生成新的镜像文件fsimage checkpoint7、拷贝fsimage checkpoint到NameNode8、NameNode将fsimage checkpoint重新命名成fsimage

    2.Fsimage和Edits进步解析?

    NameNode被格式化之后,将在/opt/module/hadoop/data/tmp/dfs/name/current目录中产生如下文件

    fsimage_000000000000000000fsimage_000000000000000000.md5seen_txidversion

    Fsimage文件:HDFS文件系统元数据的一个永久性检查点,里面包含HDFS文件系统的所有目录和文件inode的序列化信息;

    Edits文件:存放文件系统所有的写操作,客户端执行的写操作首次会被记录到Edits文件中;

    seen_txid文件:保存最后一个edits_的数字; 注:每次NameNode启动的时候都会将fsimage文件读到内存,加载Edits里面的更新操作,保证内存中的元数据信息都是最新的。

    3.Fsimage中为什么没有记录DataNode?

    通过查看fsimage_000000000000000000文件,我们并不能看到关于记录块对应的DataNode的信息,为什么?

    答:集群启动后,要求DataNode上报数据块信息,并隔一段时间再次上报。

    4.CheckPoint时间设置

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

    hdfs-default.xml

    <property> <name>dfs.namenode.checkpoint.period</name> <value>3600</value> </property>

    2)自定义

    <property> <name>dfs.namenode.checkpoint.txns</name> <value>1000000</value> <description>操作动作次数</description> </property> <property> <name>dfs.namenode.checkpoint.check.period</name> <value>60</value> <description> 1分钟检查一次操作次数</description> </property >

    5.Secondary NameNode中的元数据完整吗?

    答:当NameNode故障,通过Secondary NameNode恢复的元数据是不完整的,最新编辑日志的元数据丢失,这些数据还没有Checkpoint。

    6.集群安全模式

    1)集群处于安全模式,不能执行重要操作(写操作)。集群启动完成后,自动退出安全模式。

    查看当前模式

    hdfs dfsadmin -safemode get Safe mode is OFF bin/hdfs dfsadmin -safemode get (功能描述:查看安全模式状态) bin/hdfs dfsadmin -safemode enter (功能描述:进入安全模式状态) bin/hdfs dfsadmin -safemode leave (功能描述:离开安全模式状态) bin/hdfs dfsadmin -safemode wait (功能描述:等待安全模式状态)

    四、DataNode

    1.工作机制

    步骤详述1、一个数据块在DataNode上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。2、DataNode启动后向NameNode注册,通过后,周期性(1小时)的向NameNode上报所有的块信息。3、心跳是每3秒一次,心跳返回结果带有NameNode给该DataNode的命令如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟没有收到某个DataNode的心跳,则认为该节点不可用。4、集群运行中可以安全加入和退出一些机器。

    2.DataNode上数据损坏,怎么办?

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

    DataNode读取Block的时候,会计算CheckSum若计算的CheckSum,与Block创建时值不一样,说明Block已经损坏Client读取其他DataNode上的BlockDataNode在其文件创建后周期性验证CheckSum

    3.退役节点

    添加白名单:添加到白名单的主机节点,都允许访问NameNode,不在白名单的主机节点,都会被退出。 1)在NameNode的/opt/module/hadoop-3.1.3/etc/hadoop目录下创建dfs.hosts文件

    hadoop01 hadoop02 hadoop03

    2)在NameNode的hdfs-site.xml配置文件中增加dfs.hosts属性

    <property> <name>dfs.hosts</name> <value>/opt/module/hadoop-3.1.3/etc/hadoop/dfs.hosts</value> </property>

    3)配置文件分发 4)刷新NameNode

    hdfs dfsadmin -refreshNodes

    5)更新ResourceManager节点

    yarn rmadmin -refreshNodes

    6)如果数据不均衡,可以用命令实现集群的再平衡

    [yilei@hadoop02 sbin]$ ./start-balancer.sh

    总结

    关于HDFS的内容就总结到这里,欢迎小伙伴们给与指正,同时如果对你有帮助,也劳驾动起你的小手手,投币三联哦!!!

    Processed: 0.017, SQL: 9