草庐IT

图文详解 HDFS 的工作机制及其原理

datadance 2023-03-28 原文

大家好,我是大D。

今天开始给大家分享关于大数据入门技术栈——Hadoop的学习内容。

初识 Hadoop

为了解决大数据中海量数据的存储与计算问题,Hadoop 提供了一套分布式系统基础架构,核心内容包含HDFS ( Hadoop Distributed File System, 分布式文件系统)、MapReduce计算引擎和YARN (Yet Another Resource Negotiator,另一种资源协调者)统一资源管理调度。

随着大数据技术的更新迭代,如今 Hadoop 不再是一个单独的技术,而是一套大数据处理的生态圈,如下图所示。

除了上述提到的 Hadoop 三个核心组件之外,还有数据采集工具Sqoop与Flume,它们可以将海量数据抽取到Hadoop平台上,进行后续的大数据分析;ZooKeeper能够保证Hadoop集群在部分节点宕机的情况下依然可靠运行(干货总结!一文搞定 ZooKeeper ,面试再也不用背八股(文末送PDF));基于Hadoop运算平台的数据仓库Hive、流式计算Storm、数据挖掘工具Mahout和分布式数据库HBase等大数据技术框架。

HDFS

HDFS (Hadoop Distributed File System, 分布式文件系统) 是Google公司的GFS论文思想的实现,也作为 Hadoop 的存储系统,它包含客户端(Client)、元数据节点(NameNode)、备份节点(Secondary NameNode)以及数据存储节点(DataNode)。

Client

HDFS 利用分布式集群节点来存储数据,并提供统一的文件系统访问接口。这样,用户在使用分布式文件系统时就如同在使用普通的单节点文件系统一样,仅通过对 NameNode 进行交互访问就可以实现操作HDFS中的文件。HDFS提供了非常多的客户端,包括命令行接口、Java API、Thrift接口、Web界面等。

NameNode

NameNode 作为 HDFS 的管理节点,负责保存和管理分布式系统中所有文件的元数据信息,如果将 HDFS 比作一本书,那么 NameNode 可以理解为这本书的目录。

其职责主要有以下三点:

  1. 负责接收 Client 发送过来的读写请求;
  2. 管理和维护HDFS的命名空间: 元数据是以镜像文件(fsimage)和编辑日志(editlog)两种形式存放在本地磁盘上的,可以记录 Client 对 HDFS 的各种操作,比如修改时间、访问时间、数据块信息等。
  3. 监控和管理DataNode:负责监控集群中DataNode的健康状态,一旦发现某个DataNode宕掉,则将该 DataNode 从 HDFS 集群移除并在其他 DataNode 上重新备份该 DataNode 的数据(该过程被称为数据重平衡,即rebalance),以保障数据副本的完整性和集群的高可用性。

SecondaryNameNode

SecondaryNameNode 是 NameNode 元数据的备份,在NameNode宕机后,SecondaryNameNode 会接替 NameNode 的工作,负责整个集群的管理。并且出于可靠性考虑,SecondaryNameNode 节点与 NameNode 节点运行在不同的机器上,且 SecondaryNameNode 节点与 NameNode 节点的内存要一样大。

同时,为了减小 NameNode 的压力,NameNode 并不会自动合并 HDFS中的元数据镜像文件(fsimage)和编辑日志(editlog),而是将该任务交由 SecondaryNameNode 来完成,在合并完成后将结果发送到NameNode, 并再将合并后的结果存储到本地磁盘。

DataNode

存放在HDFS上的文件是由数据块组成的,所有这些块都存储在DataNode节点上。DataNode 负责具体的数据存储,并将数据的元信息定期汇报给 NameNode,并在 NameNode 的指导下完成数据的 I/O 操作。

实际上,在DataNode节点上,数据块就是一个普通文件,可以在DataNode存储块的对应目录下看到(默认在$(dfs.data.dir)/current的子目录下),块的名称是 blk_ID,其大小可以通过dfs.blocksize设置,默认为128MB。

初始化时,集群中的每个 DataNode 会将本节点当前存储的块信息以块报告的形式汇报给 NameNode。在集群正常工作时,DataNode 仍然会定期地把最新的块信息汇报给 NameNode,同时接收 NameNode 的指令,比如创建、移动或删除本地磁盘上的数据块等操作。

HDFS数据副本

HDFS 文件系统在设计之初就充分考虑到了容错问题,会将同一个数据块对应的数据副本(副本个数可设置,默认为3)存放在多个不同的 DataNode 上。在某个 DataNode 节点宕机后,HDFS 会从备份的节点上读取数据,这种容错性机制能够很好地实现即使节点故障而数据不会丢失。

HDFS的工作机制

NameNode 工作机制

NameNode简称NN

  • NN 启动后,会将镜像文件(fsimage)和编辑日志(editlog)加载进内存中;
  • 客户端发来增删改查等操作的请求;
  • NN 会记录下操作,并滚动日志,然后在内存中对操作进行处理。

SecondaryNameNode工作机制

SecondaryNameNode简称2NN

  • 当编辑日志数据达到一定量或者每隔一定时间,就会触发 2NN 向 NN 发出 checkpoint请求;
  • 如果发出的请求有回应,2NN 将会请求执行 checkpoint 请求;
  • 2NN 会引导 NN 滚动更新编辑日志,并将编辑日志复制到 2NN 中;
  • 同编辑日志一样,将镜像文件复制到 2NN 本地的 checkpoint 目录中;
  • 2NN 将镜像文件导入内存中,回放编辑日志,将其合并到新的fsimage.ckpt;
  • 将 fsimage.ckpt 压缩后写入到本地磁盘;
  • 2NN 将 fsimage.ckpt 传给 NN;
  • NN 会将新的 fsimage.ckpt 文件替换掉原来的 fsimage,然后直接加载和启用该文件。

HDFS文件的读取流程

  • 客户端调用 FileSystem 对象的open()方法,其实获取的是一个分布式文件系统(DistributedFileSystem)实例;
  • 将所要读取文件的请求发送给 NameNode,然后 NameNode 返回文件数据块所在的 DataNode 列表(是按照 Client 距离 DataNode 网络拓扑的远近进行排序的),同时也会返回一个文件系统数据输入流(FSDataInputStream)对象;
  • 客户端调用 read() 方法,会找出最近的 DataNode 并连接;
  • 数据从 DataNode 源源不断地流向客户端。

HDFS文件的写入流程

  • 客户端通过调用分布式文件系统(DistributedFileSystem)的create()方法创建新文件;
  • DistributedFileSystem 将文件写入请求发送给 NameNode,此时 NameNode 会做各种校验,比如文件是否存在,客户端有无权限去创建等;
  • 如果校验不通过则会抛出I/O异常。如果校验通过,NameNode 会将该操作写入到编辑日志中,并返回一个可写入的 DataNode 列表,同时,也会返回文件系统数据输出流(FSDataOutputStream)的对象;
  • 客户端在收到可写入列表之后,会调用 write() 方法将文件切分为固定大小的数据包,并排成数据队列;
  • 数据队列中的数据包会写入到第一个 DataNode,然后第一个 DataNode 会将数据包发送给第二个 DataNode,依此类推。
  • DataNode 收到数据后会返回确认信息,等收到所有 DataNode 的确认信息之后,写入操作完成。

最后

更多图解大数据技术的干货文章,关注公众号: Data跳动,回复:图解系列。
另外,非常欢迎大家扫描下方二维码,加我VX:Abox_0226,备注「进群」,有关大数据技术的问题在群里一起探讨。

有关图文详解 HDFS 的工作机制及其原理的更多相关文章

  1. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  2. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  3. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

    我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

  4. ruby-on-rails - rspec should have_select ('cars' , :options => ['volvo' , 'saab' ] 不工作 - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request

  5. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  6. ruby - JetBrains RubyMine 3.2.4 调试器不工作 - 2

    使用Ruby1.9.2运行IDE提示说需要gemruby​​-debug-base19x并提供安装它。但是,在尝试安装它时会显示消息Failedtoinstallgems.Followinggemswerenotinstalled:C:/ProgramFiles(x86)/JetBrains/RubyMine3.2.4/rb/gems/ruby-debug-base19x-0.11.30.pre2.gem:Errorinstallingruby-debug-base19x-0.11.30.pre2.gem:The'linecache19'nativegemrequiresinstall

  7. ruby - `rescue $!` 是如何工作的? - 2

    我知道全局变量$!包含最新的异常对象,但我对下面的语法感到困惑。谁能帮助我理解以下语法?rescue$! 最佳答案 此构造可防止异常停止您的程序并使堆栈跟踪冒泡。它还会将该异常作为值返回,这很有用。a=get_me_datarescue$!在此行之后,a将保存请求的数据或异常。然后您可以分析该异常并采取相应措施。defget_me_dataraise'Nodataforyou'enda=get_me_datarescue$!puts"Executioncarrieson"pa#>>Executioncarrieson#>>#更现实的

  8. ruby - File.read ("| echo mystring") 是如何工作的? - 2

    我在我正在处理的一些代码中发现了这一点。它旨在解决从磁盘读取key文件的要求。在生产环境中,key文件的内容位于环境变量中。旧代码:key=File.read('path/to/key.pem')新代码:key=File.read('|echo$KEY_VARIABLE')这是如何工作的? 最佳答案 来自IOdocs:Astringstartingwith“|”indicatesasubprocess.Theremainderofthestringfollowingthe“|”isinvokedasaprocesswithappro

  9. ruby - 这个 ruby​​ 注入(inject)魔术是如何工作的? - 2

    我今天看到了一个ruby​​代码片段。[1,2,3,4,5,6,7].inject(:+)=>28[1,2,3,4,5,6,7].inject(:*)=>5040这里的注入(inject)和之前看到的完全不一样,比如[1,2,3,4,5,6,7].inject{|sum,x|sum+x}请解释一下它是如何工作的? 最佳答案 没有魔法,符号(方法)只是可能的参数之一。这是来自文档:#enum.inject(initial,sym)=>obj#enum.inject(sym)=>obj#enum.inject(initial){|mem

  10. ruby-on-rails - attr_accessible 在 Rails 中如何工作? - 2

    我刚刚有一个关于RubyonRails和模型(Rails3)中的attr_accessible属性的一般性问题。有人可以解释应该在那里定义哪些模型属性吗?我记得一些关于批量分配风险的事情,虽然我在这方面不太了解......谢谢:) 最佳答案 想象一个带有一些字段的订单类:Order.new({:type=>'Corn',:quantity=>6})现在假设订单也有折扣代码,比如:price_off。您不想将:price_off标记为attr_accessible。这会阻止恶意代码制作最终会执行如下操作的帖子:Order.new({:

随机推荐