5、学习大数据笔记-HDFS(Hadoop Distributed File System)

1,437 阅读10分钟

部分参考-->HDFS读写流程(史上最精炼详细)

一、Hadoop是什么

HDFS全称:Hadoop Distributed File System  Hadoop分布式文件系统
Hadoop由三个模块组成:分布式存储HDFS、分布式计算MapReduce、资源调度引擎Yarn

分布式:利用一批通过网络连接的、廉价普通的机器,完成单个机器无法完成的存储、计算任务
HDFS是什么?
   Hadoop分布式文件系统,适合存储大文件,不适合存储小文件

为什么使用HDFS?
    高可用、容错、可扩展

二、核心概念block

HDFS block块:
HDFS3.x上的文件,是按照128M为单位,切分成一个个block,分散的存储在集群的不同数据节点datanode上

block副本
- replication = 3
- hdfs-site.xml

    <property>
	<name>dfs.replication</name>
	<value>3</value>    #设置同一block块的数量,默认是3
    </property>

实际机房中,会有机架,每个机架上若干服务器

block的一些操作:
设置文件副本数:hadoop fs -setrep -R 4 /path
查看文件的块信息:hdfs fsck /02-041-0029.mp4 -files -blocks -locations

三、HDFS体系架构

HDFS是主从架构Master/Slave、管理节点/工作节点

NameNode:相当于windos中文件属性信息
HDFS也是fs,它也有metadata;由NameNode存储在其内存中
1. 管理节点,负责管理文件系统和命名空间,存放了HDFS的元数据;
2. 元数据:文件系统树、所有的文件和目录、每个文件的块列表、块所在的datanode等;
3. 文件、block、目录占用大概150Byte字节的元数据;所以HDFS适合存储大文件,不适合存储小文件
4. 元数据信息以命名空间镜像文件fsimage和编辑日志(edits log)的方式保存
          fsimage:元数据镜像文件 ,保存了文件系统目录树信息以及文件和块的对应关系
          edits log:日志文件 ,保存文件系统的更改记录

DataNode:存储block,以及block元数据包括数据块的长度、块数据的校验和、时间戳
SeconddaryNameNode:它一般部署在另外一台节点上,因为它需要占用大量的CPU时间,并需要与namenode一样多的内存,来执行合并操作

HDFS机制:心跳机制

工作原理:
1. master启动的时候,会开一个ipc server在那里。
2. slave启动,连接master,每隔3秒钟向master发送一个“心跳”,携带状态信息;
3. master通过这个心跳的返回值,向slave节点传达指令

作用:
1. Namenode全权管理数据块的复制,它周期性地从集群中的每个Datanode接收心跳信号和块状态报告(Blockreport)。接收到心跳信号意味着该Datanode节点工作正常。块状态报告包含了一个该       Datanode上所有数据块的列表
2. DataNode启动后向NameNode注册,通过后,周期性(1小时)的向 NameNode上报所有的块的列表;
   每3秒向NamNode发一次心跳,返回NameNode给该DataNode的命令;如复制块数据到另一台机器,或删除某个数据块。如果NameNode超过10分钟没有收 到某个DataNode 的心跳,则认为该节点不可用。
3. hadoop集群刚开始启动时,会进入安全模式(99.9%),就用到了心跳机制


负载均衡:
Hadoop的HDFS集群非常容易出现机器与机器之间磁盘利用率不平衡的情况,例如:当集群内新增、删除节点,或者某个节点机器内硬盘存储达到饱和值。当数据不平衡时,Map任务可能会分配到没有存储数据的机器,这将导致网络带宽的消耗,也无法很好的进行本地计算。
当HDFS负载不均衡时,需要对HDFS进行数据的负载均衡调整,即对各节点机器上数据的存储分布进行调整。从而,让数据均匀的分布在各个DataNode上,均衡IO性能,防止热点的发生。进行数据的负载均衡调整,必须要满足如下原则:

数据平衡不能导致数据块减少,数据块备份丢失
管理员可以中止数据平衡进程
每次移动的数据量以及占用的网络资源,必须是可控的
数据均衡过程,不能影响namenode的正常工作

HDFS 数据自动平衡脚本

#启动数据均衡,默认阈值为 10%
$Hadoop_home/bin/start-balancer.sh

#启动数据均衡,阈值 5%
bin/start-balancer.sh –threshold 5

#停止数据均衡
$Hadoop_home/bin/stop-balancer.sh


HDFS读写流程:
block、packet、chunk区别:
block 
文件上传前需要分块,这个块就是block,一般为128MB,当然你可以去改,不顾不推荐。因为块太小:寻址时间占比过高。块太大:Map任务数太少,作业执行速度变慢。它是最大的一个单位。

packet 
packet是第二大的单位,它是client端向DataNode,或DataNode的PipLine之间传数据的基本单位,默认64KB。

chunk 
chunk是最小的单位,它是client向DataNode,或DataNode的PipLine之间进行数据校验的基本单位,默认512Byte,因为用作校验,故每个chunk需要带有4Byte的校验位。所以实际每个chunk写入packet的大小为516Byte。由此可见真实数据与校验值数据的比值约为128 : 1。(即64*1024 / 512)

例如,在client端向DataNode传数据的时候,HDFSOutputStream会有一个chunk buff,写满一个chunk后,会计算校验和并写入当前的chunk。之后再把带有校验和的chunk写入packet,当一个packet写满后,packet会进入dataQueue队列,其他的DataNode就是从这个dataQueue获取client端上传的数据并存储的。同时一个DataNode成功存储一个packet后之后会返回一个ack packet,放入ack Queue中。

HDFS读流程:

详细步骤:
client访问NameNode,查询元数据信息,获得这个文件的数据块位置列表,返回输入流对象。
就近挑选一台datanode服务器,请求建立输入流 。
DataNode向输入流中中写数据,以packet为单位来校验。
关闭输入流

1. 客户端与NameNode通讯获取文件的块位置信息,其中包括了块的所有冗余备份的位置信息:DataNode的列表
2. 客户端获取文件位置信息后直接同有文件块的DataNode通讯,读取文件
3. 如果第一个DataNode无法连接,客户端将自动联系下一个DataNode
4. 如果块数据的校验值出错,则客户端需要向NameNode报告,并自动联系下一个DataNode 

HDFS写流程:

详细步骤:
    客户端向NameNode发出写文件请求。
    检查是否已存在文件、检查权限。若通过检查,直接先将操作写入EditLog,并返回输出流对象。 
    (注:WAL,write ahead log,先写Log,再写内存,因为EditLog记录的是最新的HDFS客户端执行所有的写操作。如果后续真实写操作失败了,由于在真实写操作之前,操作就被写入EditLog中了,故EditLog中仍会有记录,我们不用担心后续client读不到相应的数据块,因为在第5步中DataNode收到块后会有一返回确认信息,若没写成功,发送端没收到确认信息,会一直重试,直到成功)
    client端按128MB的块切分文件。
    client将NameNode返回的分配的可写的DataNode列表和Data数据一同发送给最近的第一个DataNode节点,此后client端和NameNode分配的多个DataNode构成pipeline管道,client端向输出流对象中写数据。client每向第一个DataNode写入一个packet,这个packet便会直接在pipeline里传给第二个、第三个…DataNode。 
    (注:并不是写好一个块或一整个文件后才向后分发)
    每个DataNode写完一个块后,会返回确认信息。 
    (注:并不是每写完一个packet后就返回确认信息,个人觉得因为packet中的每个chunk都携带校验信息,没必要每写一个就汇报一下,这样效率太慢。正确的做法是写完一个block块后,对校验信息进行汇总分析,就能得出是否有块写错的情况发生)
    写完数据,关闭输输出流。
    发送完成信号给NameNode。 
    (注:发送完成信号的时机取决于集群是强一致性还是最终一致性,强一致性则需要所有DataNode写完后才向NameNode汇报。最终一致性则其中任意一个DataNode写完后就能单独向NameNode汇报,HDFS一般情况下都是强调强一致性)

读写过程,数据完整性如何保持?
    通过校验和。因为每个chunk中都有一个校验位,一个个chunk构成packet,一个个packet最终形成block,故可在block上求校验和。

    HDFS 的client端即实现了对 HDFS 文件内容的校验和 (checksum) 检查。当客户端创建一个新的HDFS文件时候,分块后会计算这个文件每个数据块的校验和,此校验和会以一个隐藏文件形式保存在同一个 HDFS 命名空间下。当client端从HDFS中读取文件内容后,它会检查分块时候计算出的校验和(隐藏文件里)和读取到的文件块中校验和是否匹配,如果不匹配,客户端可以选择从其他 Datanode 获取该数据块的副本。
    
    HDFS中文件块目录结构具体格式如下:
    ${dfs.datanode.data.dir}/ 
    ├── current 
    │ ├── BP-526805057-127.0.0.1-1411980876842 
    │ │ └── current 
    │ │ ├── VERSION 
    │ │ ├── finalized 
    │ │ │ ├── blk_1073741825 
    │ │ │ ├── blk_1073741825_1001.meta 
    │ │ │ ├── blk_1073741826 
    │ │ │ └── blk_1073741826_1002.meta 
    │ │ └── rbw 
    │ └── VERSION 
    └── in_use.lock
    
    in_use.lock表示DataNode正在对文件夹进行操作 
    rbw是“replica being written”的意思,该目录用于存储用户当前正在写入的数据。 
    Block元数据文件(*.meta)由一个包含版本、类型信息的头文件和一系列校验值组成。校验和也正是存在其中。

Hadoop HA高可用

Hadoop之HA高可用性

Hadoop——HDFS HA与联邦原理

Hadoop联邦

1 为什么需要高可用与联邦
- 集群的元数据保存在namenode内存中
- 每个文件、目录、block占用约150字节
- 对于一个拥有大量文件的超大集群来说,内存将成为限制系统横向扩展的瓶颈。

2 联邦

HDFS编程:下一个笔记记录

存储大量小文件

- NameNode存储着文件系统的元数据,每个文件、目录、块大概有150字节的元数据;
- 因此文件数量的限制也由NN内存大小决定,如果小文件过多则会造成NN的压力过大

解决方案:
1、HAR文件方案(本质启动mr程序,所以需要启动yarn)

# 创建archive文件
hadoop archive -archiveName test.har -p /testhar -r 3 th1 th2 /outhar # 原文件还存在,需手动删除
# 查看archive文件
hdfs dfs -ls -R har:///outhar/test.har
# 解压archive文件
hdfs dfs -cp har:///outhar/test.har/th1 hdfs:/unarchivef
hadoop fs -ls /unarchivef	# 顺序
hadoop distcp har:///outhar/test.har/th1 hdfs:/unarchivef2 # 并行,启动MR

2、Sequence Files方案
    其核心是以文件名为key,文件内容为value组织小文件。10000个100KB的小文件,可以编写程序
    将这些文件放到一个SequenceFile文件,然后就以数据流的方式处理这些文件,也可以使用
    MapReduce进行处理。一个SequenceFile是可分割的,所以MapReduce可将文件切分成块,每一
    块独立操作。不像HAR,SequenceFile支持压缩。在大多数情况下,以block为单位进行压缩是最好的
    选择,因为一个block包含多条记录,压缩作用在block之上,比reduce压缩方式(一条一条记录进
    行压缩)的压缩比高.把已有的数据转存为SequenceFile比较慢。比起先写小文件,再将小文件写入
    SequenceFile,一个更好的选择是直接将数据写入一个SequenceFile文件,省去小文件作为中间媒介.

    编程代码,下一个笔记记录