说起hadoop这个东西,只能说真是个伟大的发明,而本人对cutting大神也是无比的崇拜,记得刚接触hadoop的时候,还觉得这个东西挺多余的,但是现在想想,这个想法略傻逼......

2006-2016,hadoop至今已经走过了10个年头,版本也已经发展到2.7了,现在hadoop3.0也快出来了,虽然spark,flink这些优秀的框架近几年的势头非常的强劲,但是我认为,近几年内并不会有哪个框架会取代hadoop,所以其实还是挺值得研究的。

那么我这系列的文章呢,主要是想讲讲Hadoop的核心组件HDFS,这个文件系统现在应用真是非常的广泛,特别是hadoop由1.x升到2.x之后,hdfs不论是从容错性、可靠性、可扩展性都有了非常大的提升,体系结构也有了很大的变化。正巧最近忙里偷闲阅读了一下hdfs的源代码和看了一本介绍hdfs源代码的书,希望分享下我自己的一些理解吧。

首先简单说说HDFS的基本结构吧,主从式架构相信大家都非常熟悉,hadoop也是采用这一个,由namenode和datanode组成,但是在1.x版本中已经证实了仅仅依靠secondary namenode来保证hadoop集群的可靠性是远远不够的,因为secondary namenode不是热备份,而只是帮助namenode恢复数据而已,并且数据也不是恢复到最新的数据(有关secondary namenode的帮助恢复的工作原理有兴趣的朋友可以留留言,我可以简要介绍下,要是大家都有这个需求我就另发一篇讲讲这个secondary namenode,不过这个都是1.x的事了,大家应该不感兴趣吧哈哈~),因此,要保证hadoop集群的高可用,在2.x中引入了HA机制,有关这个HA机制,主要是以来zookeeper来实现的,这里先不细讲,后面我会专门写文章讲这个的,这里主要HDFS结构中几种节点的通信。

那么HDFS通信协议呢,有两种,一种是Hadoop RPC接口,一种是流式接口,那么这两种接口各自有各自的分工,前者主要是负责一些连接的管理、节点的管理以及一些数据的管理,而后者主要是数据的读写传输。

1.Hadoop RPC 接口

首先,不同于流式接口,Hadoop RPC接口是基于protobuf实现的,protobuf是google的一种数据格式,这里不做细究。那么Hadoop RPC的接口主要有那么几个,包括ClientProtocol,ClientDatanodeProtocol,DatanodeProtocol,InterDatanodeProtocol,NamenodeProtocol这几个,这几个接口都是节点间的主要通信接口,其他的一些涉及安全、HA的接口我们以后在讨论。

首先是重中之重的ClentProtocol,为什么是重中之重呢?我们需要对数据文件做的操作基本上都是靠这个接口来实现的,我看的源代码是2.6.4,大致数了下,这个接口有89十个方法,醉了......这里主要的一些方法有getBlockLocations()、create()、append()、addBlock()、comlete()等等,具体这些方法怎么我家下来介绍完集中接口之后,结合HDFS读文件和写文件的流程来介绍这些方法的使用。

然后是ClientDatanodeProtocol接口,这个接口是Client端和Datanode端通信使用的,主要有getReplicationVisibleLength()、getBlockLocalPathInfo()、refreshNamenodes()、deleteBlockPool()、getHdfsBlocksMetadata()、shutdownDatanode()这么些方法,我们从这些方法名可以看到,这些方法基本上都是与数据块的管理相关,很显然嘛,Datanode主要的用途就是存储数据嘛,他又不能自己管理数据。

那么接下来就是datanode和namenode通信的接口,DatanodeProtocol,这个接口也是非常重用,解决了很多的问题,datanode的注册、心跳应答数据块汇报都是靠这个接口完成的。这个接口里,有datanode启动相关的,心跳相关的和数据块读写相关的方法。启动相关的方法,其实主要是四个,versionRequest()、registerDatanode()、blockReport()和cacheReport(),按流程来说就是先是versionRequest(),确认namenode和datanode的版本信息是否一致,如果一直,则建立连接,然后是registerDatanode(),从名字也能看得出,这个方法是拿来注册这个datanode节点的,注册了之后namenode中才会有这个节点相关的信息,然后是blockReport()和cacheReport(),datanode汇报自己节点上的数据块信息(有人很疑问,为啥一个新的节点要汇报数据块信息?我认为应该是有些节点是因为失效了又重新加入集群中,所以里面本来就有数据)。通过这四步,datanode就成功启动加入集群了。心跳相关的方法其实主要就一个sendHeartbeat(),这个方法就是用来发送心跳的,心跳是默认3秒钟一次。最后是数据块读写相关的方法,有reportBadBlocks()、blockReceivedAndDeleted()和commitBlockSynchronization()方法,这些方法其实都是拿来管理数据块的,比如出现无效的数据块或者写数据过程中节点故障数据没写完等等。

然后是InterDatanodeProtocol接口,这个接口很简单,就是datanode之间相互通信的接口,虽然这个接口简单,但是其实很有用,因为我们所说的副本就是通过datanode之间的通信来实现复制的而不是通过namenode同时将文件数据写到三个副本中。

最后就是NamenodeProtocol了,这个接口就不说了吧,在2.x都没什么用了,这个是namenode和secondary namenode通信的接口。

2.流式接口

流式接口有两种,一种是基于TCP的DataTransferProtocol,一种是HA机制的active namenode和standby namenode间的HTTP接口,第二种先不说,因为涉及HA机制节点的切换以及fsimage和editlog的合并方式等等,这个今后另起一篇来说。

那么就是DataTransferProtocol了,这个接口最主要的方法就是readBlock()、writeBlock()和transferBlock()了。读数据块、写数据块以及数据块额复制就是靠这些方法来实现。

介绍完两类接口之后,我们应该是还有一个问题没有解决吧,嘿嘿,hdfs的读写文件问题。二话不说,先来两张图:

第一张图是读数据的,第二张图是写数据的,这两张图是官方给的图。

先说说读文件,首先是HDFS客户端会调用DistributedFileSystem.open()打开跟集群的连接,并且打开文件,这个方法底层来说会调用ClientProtocol接口的open()方法,然后返回一个数据流给客户端,此时客户端会在调用接口的getBlockLocations()方法得到文件的一个数据块的位置等等信息,然后客户端就会通过数据流调用read()方法从这些位置信息里面选出一个最有的节点来进行数据读取(一般三个副本位置会选取网络开销最少的那个节点,本地节点就好了),传输完毕之后,客户端会再调用getBlockLocations()方法得到下一个数据块的位置信息,然后开始读,知道数据读取结束,客户端调用close()方法,关闭数据流。

说完读文件,就是写文件了,写文件就稍微比读文件要复杂一些。首先客户端会调用DistributedFileSystem.create()方法在hdfs中创建一个新的空文件,这个方法会在底层调用ClientProtocol.create()方法,namenode会在文件目录树下添加一个新的文件,并且将操作更新到editlog中,此举之后,集群会返回一个数据输出流,然后客户端就可以开始通过调用write()方法写数据到数据流中了,但是此时namenode中并没有任何这个数据的数据块元数据映射,所以数据流会调用addBlock()方法获取要写入datanode节点的信息,然后就是write()方法的调用写数据了,写到一个节点上之后,这个节点就开始建立与另外的datanode的连接,然后将数据复制到其他datanode,从而实现副本。当副本写完之后,第一个datanode就会返回一个确认包,确认数据已经写入完毕,并且调用blockReceivedAndDeleted()方法告诉namenode要更新内存元数据的数据,然后开始下一个数据块的写入,当数据写入完毕之后,调用close()方法关闭数据流。

追加写文件其实流程上跟写文件差不多,这里就不多做赘述了。

好了,写了那么多,主要是一个warming up,大致介绍下hdfs的一些基本原理和流程,接下来的文章里,希望能够更大家分享一些更细节的东西和hdfs内部的一些实现。共勉~

PS:本人的博客会先更新在简书上然后再更新博客,个人感觉简书对于知识的传播还是挺方便的哈哈~

Hadoop源码之HDFS(1)--------通信方式的更多相关文章

  1. hadoop源码剖析--hdfs安全模式

    一.什么是安全模式 hadoop安全模式是name node的一种状态,处于该状态时有种量特性: 1.namenode不接受任何对hfds文件系统的改变操作(即此时整个文件系统处于只读状态): 2.不 ...

  2. Hadoop源码编译过程

    一.           为什么要编译Hadoop源码 Hadoop是使用Java语言开发的,但是有一些需求和操作并不适合使用java,所以就引入了本地库(Native Libraries)的概念,通 ...

  3. 如何导入hadoop源码到eclipse

    需要进一步学习hadoop.需要看看内部源码实现,因此需要将hadoop源码导入都eclipse中. 简单总结一下,具体步骤如下: 首先确保已经安装了git.maven3.protobuf2.5.如果 ...

  4. 安装Hadoop系列 — 导入Hadoop源码项目

    将Hadoop源码导入Eclipse有个最大好处就是通过 "ctrl + shift + r" 可以快速打开Hadoop源码文件. 第一步:在Eclipse新建一个Java项目,h ...

  5. 详细讲解Hadoop源码阅读工程(以hadoop-2.6.0-src.tar.gz和hadoop-2.6.0-cdh5.4.5-src.tar.gz为代表)

    首先,说的是,本人到现在为止,已经玩过.                   对于,这样的软件,博友,可以去看我博客的相关博文.在此,不一一赘述! Eclipse *版本 Eclipse *下载 Jd ...

  6. Mac搭建Hadoop源码阅读环境

    1.本次Hadoop源码阅读环境使用的阅读工具是idea,Hadoop版本是2.7.3.需要安装的工具包括idea.jdk.maven.protobuf等 2.jdk,使用的版本是1.8版,在jdk官 ...

  7. Eclipse导入Hadoop源码项目及编写Hadoop程序

    一 Eclipse导入Hadoop源码项目 基本步骤: 1)在Eclipse新建一个java项目[hadoop-1.2.1] 2)将Hadoop压缩包解压目录src下的core,hdfs,mapred ...

  8. Centos7下编译CDH版本hadoop源码支持Snappy压缩

    1 下载snappy包并编译 wget https://github.com/google/snappy/releases/download/1.1.3/snappy-1.1.3.tar.gz tar ...

  9. Hadoop源码学习笔记之NameNode启动场景流程一:源码环境搭建和项目模块及NameNode结构简单介绍

    最近在跟着一个大佬学习Hadoop底层源码及架构等知识点,觉得有必要记录下来这个学习过程.想到了这个废弃已久的blog账号,决定重新开始更新. 主要分以下几步来进行源码学习: 一.搭建源码阅读环境二. ...

随机推荐

  1. 开启MySQL日志

    找到my.ini(Linux下是my.cnf)文件,在文件里加入下面两行: log="F:/mysqllog/mysql.log" log-bin="F:/mysqllo ...

  2. font-family常见字体

    font-family:"Times New Roman",Georgia,Serif font-family:Arial,Verdana,Sans-serif font-fami ...

  3. Delphi 收藏

    日前整理仓库,翻出了一些 Delphi 产品,以前购买的 Delphi 都有实体产品,包含说明书.光碟片.还有一些广告文宣,而且相当厚实,版本的演进,从外包装也能感受到,到目前的 XE5 版,只剩一个 ...

  4. AES .net 、JS 相互加密解密

    /// <summary> /// AES加密 /// </summary> public class AES { /// <summary> /// 加密 /// ...

  5. 如何创建C# Closure ?

    JavaScript中一个重要的概念就是闭包,闭包在JavaScript中有大量的应用,但是你知道么?C#也可以创建Closure.下面就介绍一下如何在C#中创建神奇的闭包. 在这之前,我们必须先知道 ...

  6. Ideal Forms – 帮助你建立响应式 HTML5 表单

    Ideal Forms 是建立和验证响应式 HTML5 表单的终极框架.它刚刚发布 V3 版本,更小,更快,更具可扩展性.它支持实时验证,完全自适应(适应容器,没有 CSS 媒体查询需要),键盘支持, ...

  7. 【zepto学习笔记03】事件机制

    前言 我们今天直接进入事件相关的学习,因为近期可能会改到里面的代码就zepto来说,我认为最重要的就是选择器与事件相关了,随着浏览器升级,选择器简单了,而事件相关仍然是核心,今天我们就来学习学习 ze ...

  8. yum源的配置(centos6.5)

    # cd /etc/yum.repos.d/ # mv CentOS-Base.repo CentOS-Base.repo.bak # wget http://mirrors.163.com/.hel ...

  9. Atitit.git的存储结构and 追踪

    Atitit.git的存储结构and 追踪 1. Add index.js 2 index1 1.1. new1 1.2. Modify1 2. Commit1 1. Add index.js 2 i ...

  10. 100个高质量Java开发者博客

    ImportNew注:原文中还没有100个.作者希望大家一起来推荐高质量的Java开发博客,然后不段补充到这个列表.欢迎你也参与推荐优质的Java开发博客.(声明一下:我们的数学不是体育老师教的!:) ...