浅析Hadoop(一)之HDFS
再次看hadoop权威指南,又有了一些不一样的收获,所以心血来潮,就想将我理解和整理的东西写出来,还有很多不足,欢迎大家指正。
1. hdfs的特点
- 一次写入,多次读取
- 硬件要求低
- 高延时性,高吞吐量,牺牲低延时,获得高吞吐
- 不适合大量的小文件存储
- Hdfs的文件只能有一个writer,写操作只能追加,而不能修改。
构建与磁盘上的文件系统的数据块一般为磁盘块的整数倍,磁盘块大小默认512字节,hdfs也有数据块的概念,大小为128M,而在hdfs上,小于128M的文件存储为一个数据块,并不会占满整个块的空间。数据块设置到这么大的原因是为了最小化寻址开销,这是相对于传输速率来说的,假设寻址时间为10ms,磁盘传输速率为100MB/s,为了使寻址时间只占传输时间的1%,我们会将块的大小设置为100MB。随着磁盘驱动器传输速率的增大,块的大小也会设置的更大
3. 分布式文件系统带来的好处
- 一个文件的大小可以大于网络中任意一个磁盘的容量,文件的块并不需要存储在同一磁盘上,因此他们可以利用集群上的任意一个磁盘进行存储
- 使用块作为基本存储单元,而不是文件的好处就是大大简化了系统的设计,因为块的大小是固定的。
- 块还非常适合数据备份从而提供数据容错能力和提高可用性,hdfs会将块复制到少数几个独立的节点上,默认副本为三个,这样确保在节点故障时数据不会丢失。
HDFS集群有两类节点以管理——工作者模式运行,即一个namenode和多个datanode节点
- namenode管理文件系统的命名空间,他维护着文件系统树和整棵树内所有的文件和目录,这些文件形式永久保存在本地磁盘上,由dfs.namenode.name.dir配置,这些文件以命名空间镜像文件(fsimage)和编辑日志文件(edits)进行保存,namenode同时还记录每个文件中各个块所在的数据节点信息,但是这些信息并不会持久化到本地,而是保存在内存中,并在每次namenode启动的时候由datanode发送给namenode。
- datanode是文件系统的工作节点,他们根据需要存储并检索数据块(受client或者namenode调度),并且定期向namenode发送他们所存储的块列表。
5. namenode的容错机制
运行一个辅助namenode,也就是secondarynamenode,这个辅助的namenode的作用是定期将namenode所存储的edits文件合并称为fsimage文件,以防止编辑日志过大,一般这个辅助namenode会单独工作在一个节点上,因为他会占用大量的CPU与namenode相同容量的内存来执行合并操作。他会保存合并后的fsimage文件的副本,并在namenode发生故障之后用于恢复数据。
6. fsimage和edits到底是什么东西?
- Edits:文件系统客户端在对hdfs执行写操作时,这些操作首先会被记录到edits文件中,也就是编辑日志文件,namenode在内存中维护文件系统的元数据;当编辑日志文件被修改时,相关元数据信息也会同步更新。内存中的元数据可支持客户端的读请求。
- Fsimage:fsimage文件是文件系统元数据的一个永久性检查点,其中包含文件系统中的所有目录和文件inode的序列化信息。每个inode是一个文件或目录的元数据的内部描述方式。对于文件来说,包含的信息有复本级别,修改时间,访问时间,访问许可,块大小,组成一个文件的块等信息;对于目录来说,包含的信息有修改时间,访问许可和配额元数据等信息。数据块存储在datanode中,但是fsimage文件并不会描述datanode,namenode将这种数据块和datanode的具体映射关系放在内存中。当namenode每次启动的时候,会向datanode索取当前的数据块列表以建立映射关系,namenode还会定期征询datanode以确保它拥有最新的块映射。
Namenode启动的时候,首先会将fsimage文件和edits文件载入内存当中,并执行edits文件中的各项操作,一旦内存中成功建立了文件系统的元数据的映像,则会创建一个新的fsimage文件和一个空的edits文件,此时namenode运行在安全模式下,文件系统处于只读的状态。在安全模式下,namenode向datanode 索取最新的块列表,将他们之间的映射关系保存在内存当中。如果满足“最小复本条件”namenode会在30秒后退出安全模式。
8. 描述hdfs的读写机制
写入机制:
1) client通过DistributedFileSystem对象调用create方法,该对象对namenode创建一个RPC调用,在文件的命名空间中新建一个文件,此时的文件并没有对应的数据块,namenode检查用户权限和是否已经存在该文件名,检查通过后DistributedFileSystem向client返回一个FSDataOurputStream,client通过该对象向文件中写入数据。
2) client写入数据时,FSOutputStream 将数据分成一个个的数据包,并写入内部队列,DataSreamer处理该队列,DataStreamer负责的是根据datanode列表要求namenode分配合适的新块用于存储数据复本。默认是3个副本,所以会有三个datanode组成一个管线,DataStreamer将数据包传输给管线中的第一个节点,第一个节点存储成功后将其传输给第二个节点,第二个节点存储成功后传输给第三个节点。
3) DataOutputStream维护着一个内部数据包队列来等待datanode的收到确认回执,收到管线中所有节点的确认信息,该数据包才会从确认队列中删除。
4) 客户端写完数据后,调用close方法,该操作会将剩余的所有数据包写入管线,并在联系到namenode且发送文件写入完成信号之前,等待确认。
读取机制:
1) Client通过调用DistributedFileSystem对象的open方法,该对象通过RPC调用namenode确定起始块的位置,namenode返回所有存储该文件块的复本地址并按照与client的距离来排序,client会从距离自己最近的datanode上读取数据块。
2) Client对输入流(FSDataInputStream)调用read方法来连续的读取数据,读取到块的末尾时,DFSInputSteam关闭与该datanode的连接,转去寻找下一个块的最佳datanode,直到读取结束。对FSDataInputStream调用close方法。