HDFS
- Hadoop Distributed File System,Hadoop分布式文件系统,基于流数据访问模式及处理超大文件的需求开发,可运行于廉价的商用服务器上,管理网络中跨多台计算机的存储。
- 具有高容错、高可靠性、高可扩展性、高获得性、高吞吐率等特性,为海量数据提供不怕故障的存储,十分便于超大数据集的处理及应用。
- 不适用于要求低延迟数据访问的应用、存储大量小文件、多用户写入、任意修改文件。
HDFS架构
HDFS采用Master/Slave(主从)架构,主要由四部分组成:HDFS Client、NameNode、DataNode和Secondary NameNode
Client: 客户端
- 文件上传时Client将文件切分为一个个Block(数据块,HDFS最基本的存储单元,默认为64M,用户可自行设置大小)然后进行存储
- 与NameNode交互获取Metadata(元数据,HDFS中文件和目录的属性信息。HDFS采用镜像文件(Fsimage)+日志文件(EditLog)的备份机制。文件的镜像文件内容包括:修改时间、访问时间、数据块大小、组成文件的数据块的存储位置信息。目录的镜像文件内容包括:修改时间、访问控制权限等信息。日志文件记录HDFS的更新操作。)
- 与DataNode交互进行读取或写入数据
- 可通过一些命令访问HDFS
- 提供一些命令来管理HDFS
NameNode: Master
- 管理HDFS的命名空间
- 管理Block映射信息
- 配置副本策略
- 处理Client读写请求
DataNode: Slave
- 在客户端或NameNode调度下存储并检索实际的Block
- 执行Block的读写操作
- 定期向NameNode发送BlockReport(数据块报告)(NameNode和DataNode间使用TCP协议进行通信。DataNode每3s向NameNode发送一个Heartbeat,每10次Heartbeat后向NameNode发送一个BlockReport报告自己的信息。通过这些信息NameNode能重建元数据并确保每个Block有足够的副本)
- 默认情况下每个DataNode保存3个副本,其中两个保存在同一机架的两个不同节点上,另一个放在不同机架的节点上
Rack: 机架
- 分布在多个机架上的大量DataNode组成HDFS集群
- 不同机架间节点通过交换机通信
- HDFS通过机架感知策略,使NameNode能确定每个DataNode所属机架ID
HDFS文件读写流程
读取:
1.调用FileSystem对象的open方法获取一个DistributedFileSystem实例
2.DistributedFileSystem通过RPC(Remote Procedure Call,远程过程调用)获得文件第一批Block的locations,同一Block按照重复数会返回多个locations,这些locations按Hadoop拓扑结构排序,距Client近的排前面
3.前两步返回一个FSDataInputStream对象,它会被封装成DFSInputStream对象,DFSInputStream可方便的管理DataNode和NameNode数据流。Client调用Read方法,DFSInputStream就会找出距Client最近的DataNode并连接
4.数据不断从DataNode流向Client
5.如果第一个Block读完了,就关闭指向第一个Block的DataNode连接,接着读取下一个Block。如果第一批Block都读完了,DFSInputStream就会到NameNode获得下一批Block的location,然后继续读
6.如果所有的Block都读完,就关闭所有的流
写入:
1.调用DistributedFileSystem的create方法创建一个新文件
2.DistributedFileSystem通过RPC调用NameNode创建一个没有Block关联的新文件。创建前NameNode会做各种校验,如文件是否存在,Client有无权限创建等。如果校验通过,NameNode就会记录下新文件,否则会抛出IO异常
3.前两步结束后返回FSDataOutputStream对象,它会被封装成DFSOutputStream,DFSOutputStream可协调NameNode和DataNode。Client开始写数据到DFSOutputStream,DFSOutputStream把数据切分成一个个小packet然后排成data queue
4.DataStreamer会处理接受data queue,它先问询NameNode这个新Block最适合存储在哪几个DataNode里,例如重复数是3,就找到3个最适合的DataNode,把它们排成一个pipeline。DataStreamer把packet按队列输出到pipeline的第一个DataNode中,第一个DataNode又把packet输出到第二个DataNode中,以此类推
5.DFSOutputStream还有一个ack queue,也由packet组成,等待DataNode的ack,当pipeline中所有DataNode都表示已经收到时akc queue才把对应的packet移除
6.client完成写数据后,关闭写入流
7.DataStreamer把剩余的packet都刷入pipeline,然后等待ack,收到最后一个ack后通知NameNode把文件标示为已完成
NameNode的HA机制
High Availability: 高可用
一个典型的HA集群中,每个NameNode为一台独立服务器,在任意时刻只有一个NameNode处于active状态,另一个处于standby状态。active的NameNode负责所有客户端操作,standby的NameNode处于从属地位,维护数据状态,随时准备切换。
运行NameNode的服务器应有相同的硬件配置
运行的JournalNode进程非常轻量,可部署在其他的服务器上。注意:必须允许至少3个节点。当然可以运行更多,但是必须是奇数个。当运行N个节点时,系统可以容忍至少(N-1)/2个节点失败而不影响正常运行
standby状态的NameNode可完成checkpoint操作,因此没必要配置Secondary NameNode、CheckpointNode、BackupNode
两个NameNode为了数据同步会通过一组称为JournalNode的独立进程进行相互通信。当active的NameNode的命名空间有任何修改时会告知大部分JournalNode进程。standby的NameNode能读取JournalNode中的变更信息,并一直监控edit log的变化,把变化应用于自己的命名空间。standby的NameNode可保证在集群出错时,命名空间已完全同步。
为确保快速切换,standby的NameNode需要知道集群中所有数据块的位置,因此所有DataNode必须配置两个NameNode的地址,向两个NameNode发送Block位置信息和Heartbeat。
对于HA集群,确保同一时刻只有一个NameNode处于active状态至关重要。否则两个NameNode的数据状态会产生分歧,可能丢失数据或产生错误。因此JournalNode必须确保同一时刻只有一个NameNode可向自己写入数据。