HDFS简介
HDFS全称:Hadoop Distribuited File System,本质上是一个分布式文件系统,可以部署在大量廉价的服务器上,提供可扩展、高可用性的文件读写服务。
与其他分布式文件系统相比,HDFS擅长的场景是大文件(一般认为字节数超过数十MB的文件为大文件)的顺序读、随机读和顺序写。
HDFS架构
HDFS集群主要有四个服务组成:NameNode、DataNode、JournalNode、ZKFailoverController。 HDFS实际存储的是block(大小默认为128M),每个文件是由若干个Block组成,block会设定一个副本数N,表示这个block写入时会写入N个数据节点。HDFS读取文件时,只需读取组成这个文件的block(读取任一副本)即可。
NameNode
NameNode存储并管理文件的元数据,元数据主要包括文件属性(文件大小、文件拥有者、组以及各个用户的访问权限等)以及文件的多个block分布在那些数据节点。
为了保证NameNode高可用性,部署两个NameNode,状态分别为active、standby,前者对外提供服务。
为了保证元数据的高效持久化,NameNode采用EditLog和FsImage的方式。元数据更改时,先做EditLog的顺序写,然后在更新内存状态。同时NameNode会有一个内部线程,周期性地把内存状态导出到磁盘持久化成FsImage。根据导出时间点,清理之前的EditLog,这个过程叫推进checkpoint。
DataNode
DataNode存放文件的block。
JournalNode
为了保证两个NameNode切换前后能读到一致的EditLog,HDFS实现了JournalNode,通过Paxos协议保证数据一致性。
ZKFailoverController
主要用来实现NameNode的自动切换。
文件写入
写入流程描述
- DFS Client在创建FSDataOutputStream时,把文件元数据发送给NameNode,得到一个文件唯一标识的fileId,再给用户返回一个OutputStream。
- 用户拿到OutputStream后,开始写数据。实际写入的是block,如果block写满后,需要DFS Client向NameNode申请新的block.block是由若干个Packet(默认64KB)组成,Packet写满后,就放入Data Queue。DataStreamer线程异步地将Packet发送DataNode,会先写入本地文件,然后发送一份到第二个DataNode,第二个发送给第三个DataNode。全部发送完毕后,最后返回Ack给DFS Client。
- 用户执行完写数据后,最后需要关闭OutputStream。否则可能会丢失数据。
文件读取
读取流程描述
- DFS Client请求NameNode,获取文件的block信息;
- DFS Client从block对应的DataNode中选取一个DataNode,对选中的DataNode创建一个BlockReader以进行数据读取;
对HBase读性能影响较大的两个因素:locality和短路读;DataNode是IO密集型服务,RegionServer是内存和CPU消耗性服务;一般两个服务部署在相同机器上。
- locality = 该文件存储在本地机器的总字节数/该文件总字节数;
- 短路读:DFS Client通过本地fd直接读取block,无需使用TCP协议栈开销;locality=1时,非短路读性能下降10%
HDFS在HBase中扮演的角色
HDFS-HBase体系是计算和存储分离架构,亲耦和架构,易替换。