Hadoop源码之HDFS(1)--------通信方式
说起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)--------通信方式的更多相关文章
- hadoop源码剖析--hdfs安全模式
一.什么是安全模式 hadoop安全模式是name node的一种状态,处于该状态时有种量特性: 1.namenode不接受任何对hfds文件系统的改变操作(即此时整个文件系统处于只读状态): 2.不 ...
- Hadoop源码编译过程
一. 为什么要编译Hadoop源码 Hadoop是使用Java语言开发的,但是有一些需求和操作并不适合使用java,所以就引入了本地库(Native Libraries)的概念,通 ...
- 如何导入hadoop源码到eclipse
需要进一步学习hadoop.需要看看内部源码实现,因此需要将hadoop源码导入都eclipse中. 简单总结一下,具体步骤如下: 首先确保已经安装了git.maven3.protobuf2.5.如果 ...
- 安装Hadoop系列 — 导入Hadoop源码项目
将Hadoop源码导入Eclipse有个最大好处就是通过 "ctrl + shift + r" 可以快速打开Hadoop源码文件. 第一步:在Eclipse新建一个Java项目,h ...
- 详细讲解Hadoop源码阅读工程(以hadoop-2.6.0-src.tar.gz和hadoop-2.6.0-cdh5.4.5-src.tar.gz为代表)
首先,说的是,本人到现在为止,已经玩过. 对于,这样的软件,博友,可以去看我博客的相关博文.在此,不一一赘述! Eclipse *版本 Eclipse *下载 Jd ...
- Mac搭建Hadoop源码阅读环境
1.本次Hadoop源码阅读环境使用的阅读工具是idea,Hadoop版本是2.7.3.需要安装的工具包括idea.jdk.maven.protobuf等 2.jdk,使用的版本是1.8版,在jdk官 ...
- Eclipse导入Hadoop源码项目及编写Hadoop程序
一 Eclipse导入Hadoop源码项目 基本步骤: 1)在Eclipse新建一个java项目[hadoop-1.2.1] 2)将Hadoop压缩包解压目录src下的core,hdfs,mapred ...
- Centos7下编译CDH版本hadoop源码支持Snappy压缩
1 下载snappy包并编译 wget https://github.com/google/snappy/releases/download/1.1.3/snappy-1.1.3.tar.gz tar ...
- Hadoop源码学习笔记之NameNode启动场景流程一:源码环境搭建和项目模块及NameNode结构简单介绍
最近在跟着一个大佬学习Hadoop底层源码及架构等知识点,觉得有必要记录下来这个学习过程.想到了这个废弃已久的blog账号,决定重新开始更新. 主要分以下几步来进行源码学习: 一.搭建源码阅读环境二. ...
随机推荐
- Scalaz(9)- typeclass:checking instance abiding the laws
在前几篇关于Functor和Applilcative typeclass的讨论中我们自定义了一个类型Configure,Configure类型的定义是这样的: case class Configure ...
- ubuntu 下安装redis 以及php扩展
下载redis wget http://download.redis.io/redis-stable.tar.gz tar xzf redis-stable.tar.gz cd redis-s ...
- mysql 导入text 到数据库
load data local infile 'f:/PhoneLocation_201601.327665.txt' into table sys_t_phone_area fields termi ...
- 七个结构模式之适配器模式(Adapter Pattern)
定义: 将一个接口转换为客户需要的另外一个接口,使接口不兼容的类型可以一起工作,也被称为包装器模式(Wrapper Patern). 结构图: Target:目标抽象类,客户所需要的接口. Adapt ...
- mysql在Windows下使用mysqldump命令备份数据库
在cmd窗口中使用mysqldump命令首先需要配置环境变量 1,在计算机中找到MySQL的安装位置,找到MySQL Workbench,比如我的是C:\Program Files\MySQL\MyS ...
- 安卓 9.png 图片的制作
安卓的九宫格png图片可以自定义拉伸的区域,所以可以很方便的适应不同宽度高度的设备. 9.png格式是很纯正的png格式,与普通的png不同的是9.png格式的图片最外围有一圈1像素的透明区域,或者说 ...
- jQuery静态方法type使用和源码分析
jQuery.type方法是检测数据类型的工具方法,在分析其用法之前先总结下js给我们提供了那些监测数据类型的方法: 一.typeof 操作符 下面是测试代码 var data=[],a='123', ...
- onMeasure流程解析
0.预备知识 我们的手机屏幕的布局其实是嵌套的,最外层是一个phoneWindow,这个view和手机屏幕一样大,里面是一个frameLayout,再里面才是我们自己写的布局文件. 我们在绘制控件前必 ...
- Java虚拟机JVM学习01 流程概述
Java虚拟机JVM学习01 流程概述 Java虚拟机与程序的生命周期 一个运行时的Java虚拟机(JVM)负责运行一个Java程序. 当启动一个Java程序时,一个虚拟机实例诞生:当程序关闭退出,这 ...
- NSFileManager和NSFileHandler的作用
NSFileManager类可以管理文件系统中的文件和目录,也可以定位.判断是否存在.创建.拷贝.删除文件和目录,还可以获得文件和目录的信息: 对于读写文件,NSFileManager只可以读写字符串 ...