1 什么是HDFS?
HDFS的全称是:Hadoop Distribute Files System,分布式文件系统
在整个Hadoop技术体系中,HDFS提供了数据分布式存储的底层技术支持。
HDFS 由三个组件构成:NameNode(NN)、DataNode(DN)、SecondaryNameNode(SNN)
NameNode是主节点,也叫Master(进程),一个hadoop集群只有一个NameNode;
DataNode是从节点,也叫Worker(进程),一个hadoop集群可以有多个DataNode;
SecondaryNameNode不是第二主节点,是助手节点,作用于数据持久化。
2 系统架构
HDFS 是一个主/从(Master/Slave)体系架构,由于分布式存储的性质,集群拥有两类节点 NameNode 和 DataNode。
NameNode(名字节点):系统中通常只有一个,中心服务器的角色,管理存储和检索多个 DataNode 的实际数据所需的所有元数据。
DataNode(数据节点):系统中通常有多个,是文件系统中真正存储数据的地方,在NameNode 统一调度下进行数据块的创建、删除和复制。
图中的Client 是 HDFS 的客户端,是应用程序可通过该模块与 NameNode 和DataNode 进行交互,进行文件的读写操作。
为什么1.0里只有一个NameNode?
因为hadoop1.0是在zookeeper诞生之前,那时候没软件满足HA。
3 NameNode与DataNode之间的联系
Heartbeat:NameNode与DataNode之间存在心跳连接,DataNode每隔一段时间就主动向NameNode汇报block的信息(heartbeats是多个datanode,多条心跳连接)
balance:当一个datanode挂了,block,为了达到平衡状态,内部数据会平均分配到其他datanode上
NameNode作用
1)管理着文件系统命名空间:维护着文件系统树及树中的所有文件和目录
2)存储元数据:NameNode保存元信息的种类有:
• 文件名目录名及它们之间的层级关系
• 文件目录的所有者及其权限
• 每个文件块的名及文件有哪些块组成
3)元数据保存在内存中
NameNode元信息并不包含每个块的位置信息(每个块的信息存储在block中,block存储在datanode中)
4)保存文件,block,datanode之间的映射关系
有2种映射关系数据:
文件名->blockid list列表
block数据块->datanode节点地址(数据是通过DN->NN发送心跳组织起来的)
5)Hadoop更倾向存储大文件原因:
一般来说,一条元信息记录会占用200byte内存空间。假设块大小为64MB,备份数量是3,那么一个1GB大小的文件将占用16*3=48个文件块。如果现在有1000个1MB大小的文件,则会占用1000*3=3000个文件块(多个文件不能放到一个块中)。我们可以发现,如果文件越小,存储同等大小文件所需要的元信息就越多,所以Hadoop更喜欢大文件。
6)元信息持久化
在NameNode中存放元信息的文件是 fsimage。在系统运行期间所有对元信息的操作都保存在内存中并被持久化到另一个文件edits中。并且edits文件和fsimage文件会被SecondaryNameNode周期性的合并。
7)运行NameNode会占用大量内存和I/O资源,一般NameNode不会存储用户数据或执行MapReduce任务。
DataNode作用
1)负责存储数据块,负责为系统客户端提供数据块的读写服务
2)根据NameNode的指示进行创建、删除和复制等操作
3)心跳机制,定期(3秒)报告文件块列表信息
4)DataNode之间进行通信,块的副本处理
Block---数据块
- 磁盘读写的基本单位
- HDFS默认数据块大小64MB,磁盘块一般为512B
- 块增大可以减少寻址时间,降低寻址时间/文件传输时间,若寻址时间为10ms,磁盘传输速率为100MB/s,那么该比例仅为1%
- 数据块过大也不好,因为一个MapReduce通常以一个块作为输入,块过大会导致整体任务数量过小,降低作业处理速度
SecondaryNameNode作用
两个文件:
fsimage:它是在NameNode启动时对整个文件系统的快照(镜像文件)
edit logs:它是在NameNode启动后,对文件系统的改动序列(存在磁盘中)
两个文件状态:数据是不断改动的,而NameNode是很少重启的,所以edit log是不断增大的,而fsimage是比较旧的,永远也赶不上edit log文件的;
NameNode重启那一瞬间,内存数据是空白的,或者NameNode挂了,丢失数据;需要数据找回
NameNode重启之后会先读fsimage,之前跟eidt,两者合并才能得到完整数据,这时edit log数据会比fsimage大很多,合并需要很长时间,这时就需要一个机制,尽可能想办法怎样减小你的eidt,并且让fsimage这个文件能够尽可能的保持最新的数据状态,这样的话NameNode重启的话就不需要有合并这样的影响了,它就可以从fsimage直接读数据然后启动。所以呢这个事情就有SecondNameNode来干的。
SecondNameNode作用:
1)用来保存HDFS的元数据信息,比如命名空间信息、块信息等,由于这些信息是在内存的,SecondNameNode是为了考虑持久化到磁盘
2)定时到NameNode去获取edit logs,并更新到fsimage[Secondary NameNode自己的fsimage]
3)一旦它有了新的fsimage文件,它将其拷贝回NameNode中。(这时有两个数据一样的fsimage)
4) NameNode在下次重启时会使用这个新的fsimage文件,从而减少重启的时间。
Secondary NameNode所做的不过是在文件系统中设置一个检查点来帮助NameNode更好的工作。它不是要取代掉NameNode也不是NameNode的备份。
SecondNamenode存在意义?(备份、数据恢复)
备份:是为了数据不丢失
数据恢复:是数据找回
NameNode把每一次改动都会存在edit log中,但是整个事件是由谁来触发的?(DataNode)
元数据持久化的过程(SNN来完成):
内存->edit log(磁盘)-> fsimage
fsimage:多久加载一次?(重启才会加载)
4 Client访问数据流程
Client访问数据流程:(先简单梳理)
Client先是访问NameNode,从NameNode中得知文件的block,从block中得知数据存储的path,也就是数据存储在哪个datanode上,之后client就直接到该datanode上读取数据。
namenode:
1、文件名-----》 block
2、block-----》 datanode
datanode:blcok----》 path
5 防止单点故障
两个方案:
1)NFS
将hadoop元数据写入到本地文件系统的同时再实时同步到一个远程挂载的网络文件系统
2)secondary NameNode:
它的作用是与NameNode进行交互,定期通过编辑日志文件合并命名空间镜像,当NameNode发生故障时它会通过自己合并的命名空间镜像副本来恢复。需要注意的是secondaryNameNode保存的状态总是滞后于NameNode,所以这种方式难免会导致丢失部分数据
6 数据块复制
为了系统容错,文件系统会对所有数据块进行副本复制多份,Hadoop 是默认 3 副本管理。
第一个副本,在客户端相同的节点(如果客户端是集群外的一台机器,就随机算节点,但是系统会避免挑选太满或者太忙的节点)
第二个副本,放在不同机架(随机选择)的节点
第三个副本,放在与第二个副本同机架但是不同节点上
所有有关块复制的决策统一由NameNode负责,NameNode 会周期性地接受集群中数据节点 DataNode 的心跳和块报告。一个心跳的到达表示这个数据节点是正常的。一个块报告包括该数据节点上所有块的列表。
比如我目前的集群环境(1个master、2个slaves),此时并不是3个副本而是2个,因为datanode数量就只有2个。
7 数据完整性校验
不希望存储和处理数据时丢失或损失数据,HDFS会对写入的数据计算检验和,并在读取数据时验证校验和
(1)校验和(传输检测---csc32)
需要校验两次:
A)client向DataNode写数据的时候,要针对所写的数据每个检查单位(512字节)创建一个单独的校验和,将该校验码和数据本身一起传送给DataNode
B)DataNode接收的时候,也要创建校验和进行校验
新生成的校验和原始的校验和不完全匹配,那么数据就会被认为是被损坏的。
(2)数据块检测程序DataBlockScanner(本地检测)
在DataNode节点上开启一个后台线程,来定期验证存储在它上所有块,这个是防止物理介质出现损减情况而造成的数据损坏。
8 容错-可靠性措施
HDFS有一套可靠性保证(保证数据完整性)
1)心跳:DN-NN
2)副本:通过数据冗余保证高可用
3)数据完整性:crc32
4)SNN,保证元数据避免一定程度上不丢失(日记文件、镜像文件)
5)空间回收:回收站(.Trash目录,在有效时间内,可以把误删数据恢复回来)
6)快照
7)报告:快报告 ./hdfs fsck /passwd -files -blocks -locations
9 HDFS特点
HDFS 专为解决大数据存储问题而产生的,其具备了以下特点:
1)HDFS 文件系统可存储超大文件
每个磁盘都有默认的数据块大小,这是磁盘在对数据进行读和写时要求的最小单位,文件系统是要构建于磁盘上的,文件系统的也有块的逻辑概念,通常是磁盘块的数倍,
通常文件系统为几千个字节,而磁盘块一般为 512 个字节。
HDFS 是一种文件系统,自身也有块(block)的概念,其文件块要比普通单一磁盘上文件系统大的多,默认是 64MB。
HDFS 上的块之所以设计的如此之大,其目的是为了最小化寻址开销。
HDFS 文件的大小可以大于网络中任意一个磁盘的容量,文件的所有块并不需要存储在一个磁盘上,因此可以利用集群上任意一个磁盘进行存储,由于具备这种分式存储的逻辑,所以可以存储超大的文件,通常 G、T、P 级别。
2)一次写入,多次读取(write-once-read-many)
一个文件经过创建、写入和关闭之后就不需要改变,这个假设简化了数据一致性的问题,同时提高数据访问的吞吐量。保证系统性能和稳定。
3)运行在普通廉价的机器上
Hadoop 的设计对硬件要求低,无需昂贵的高可用性机器上,因为在HDFS设计中充分考虑到了数据的可靠性、安全性和高可用性。
10 不适用于HDFS的场景
1)低延迟
HDFS 不适用于实时查询这种对延迟要求高的场景,例如:股票实盘。往往应对低延迟数据访问场景需要通过数据库访问索引的方案来解决,Hadoop 生态圈中的Hbase 具有这种随机读、低延迟等特点。
2)大量小文件
对于 Hadoop 系统,小文件通常定义为远小于 HDFS 的 block size(默认 64MB)的文件,由于每个文件都会产生各自的 MetaData 元数据,Hadoop 通过 Namenode来存储这些信息,若小文件过多,容易导致 Namenode 存储出现瓶颈。
3)多用户更新
为了保证并发性,HDFS 需要一次写入多次读取,目前不支持多用户写入,若要修改,也是通过追加的方式添加到文件的末尾处,出现太多文件需要更新的情况Hadoop是不支持的。针对有多人写入数据的场景,可以考虑采用 Hbase 的方案。
4)结构化数据
HDFS 适合存储半结构化和非结构化数据,若有严格的结构化数据存储场景,也可以考虑采用 Hbase 的方案。
5) 数据量并不大
通常 Hadoop 适用于 TB、PB 数据,若待处理的数据只有几十 GB 的话,不建议使用 Hadoop,因为没有任何好处。
11 HDFS写入和读取流程
1)写流程
客户端调用 create()来创建文件,Distributed File System 用 RPC 调用 NameNode节点,在文件系统的命名空间中创建一个新的文件。NameNode 节点首先确定文件原来不存在,并且客户端有创建文件的权限,然后创建新文件。Distributed File System 返回 FSDOutputStream,客户端用于写数据。客户端开始写入数据,FSDOutputStream 将数据分成块,写入 Data Queue。Data Queue 由 DataStreamer 读取,并通知 NameNode 节点分配数据节点,用来存储数据块(每块默认复制 3块)。分配的数据节点放在一个 Pipeline 里。Data Streamer 将数据块写入 Pipeline 中的第一个数据节点。第一个数据节点将数据块发送给第二个数据节点。第二个数据节点将数据发送给第三个数据节点。DFSOutputStream 为发出去的数据块保存了 Ack Queue,等待 Pipeline 中的数据节点告知数据已经写入成功。写入一个datanode都说明写入数据成功,内部datanode会数据冗余。
2)读取流程
首先 Client 通过 File System 的 Open 函数打开文件,Distributed File System 用 RPC调用 NameNode 节点,得到文件的数据块信息。对于每一个数据块,NameNode 节点返回保存数据块的数据节点的地址。Distributed File System 返回 FSDataInputStream 给客户端,用来读取数据。客户端调用 stream的 read()函数开始读取数据。FSDInputStream连接保存此文件第一个数据块的最近的数据节点。DataNode 从数据节点读到客户端(client),当此数据块读取完毕时,FSDInputStream 关闭和此数据节点的连接,然后连接此文件下一个数据块的最近的数据节点。当客户端读取完毕数据的时候,调用FSDataInputStream 的 close 函数。在读取数据的过程中,如果客户端在与数据节点通信出现错误,则尝试连接包含此数据块的下一个数据节点。失败的数据节点将被记录,以后不再连接。
12 同步和异步
同步:保证数据一致性,问题慢
异步:速度快,不能保证数据强一致
同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。
异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。
同步就是你叫我去吃饭,我听到了就和你去吃饭;如果没有听到,你就不停的叫,直到我告诉你听到了,才一起去吃饭。
异步就是你叫我,然后自己去吃饭,我得到消息后可能立即走,也可能等到下班才去吃饭。
所以,要我请你吃饭就用同步的方法,要请我吃饭就用异步的方法,这样你可以省钱。
13 HDFS&MapReduce本地模式
本地模式:保证计算框架和任务调度管理部署在同一台机器上,体现本地化原则,尽量减少数据移动开销
mapreduce有map阶段和reduce阶段
本地化原则针对map阶段,因为reduce阶段有个远程partition,不能保证是同一机器。