第三章 第二节 HDFS概念

Block(前文翻译的“块”,以后还是使用原文的block)

磁盘的block大小,是可以读写的最小单位。单一磁盘文件系统处理这些block中的数据,

它通常是磁盘block大小的整数倍。文件系统的block大小通常是几kb,而磁盘block通常是

512b。这对于只是简单读写任意长度文件的文件系统使用者来说是透明的。尽管如此,

还是有一些工具来维护文件系统,如df和fsck,它是在文件系统的block级别操作的。

HDFS同样有block的概念,但是它是一个更大的单元----默认128M。如同单一磁盘

的文件系统,HDFS中的文件也分解成block大小的数据块,独立保存在各单元中。不

像单一磁盘文件系统,如果HDFS中的文件比block小,它不会占用block的整个存储空间

(例如,一个1M的文件存储在128M的block中,它只使用1M的磁盘空间而不是128M)。

如果没有特别指明,本书的block指的是HDFS的block。

对于分布式文件系统有一个block抽象带来了几个好处。第一个显而易见的好处是:一

个文件可以比网络中的任意一个磁盘更大。不需要文件的所有block保存在同一个磁盘上,

所以它们可以使用集群上的任意一个磁盘。实际上,一个文件的block可以占用集群上的

所有磁盘,尽管这不常见。

第二,抽象block而不是抽象文件简化了子系统的存储。简易性是所有系统追求的东西,

但是它对失败方式多样化的分布式系统尤其重要。存储子系统使用block,简化了存储管理(

因为block是固定大小,它可以简单计算出在给定的磁盘上可以存储多少block)并且消除

元数据关注点(因为block只是要存储的数据块,象权限信息等文件元数据不需要存储,所以

其它的系统可以单独处理元数据)。

此外,block很适合复制以提供容错和可用性。为了防止block和磁盘毁坏、机器故障等,

每一个block都被复制到一些物理分离的机器上(典型3个)。如果一个block不可用,可以从

别一个位置读取备份,这对客户端来说是透明的。由于毁坏或机器故障而不可用的block可以

从其它可用的机器上再拷贝一份从而让备份因子回到正常水平(见97页数据整合来看更多的

数据毁坏防范)。同样的,一些应用会对于经常读取的文件的block设置高复制因子。如同

它的堂兄弟fs,HDFS的命令fsck知道block。例如,运行以下命令:

% hdfs fsck / -files -blocks

会显示文件系统中构成文件的block列表。

Namenode和Datanode

在master-worker模式中,HDFS集群有两种节点操作:一个namenode(master)和一些

datanode(worker)。namenode管理文件系统命名空间。它维护文件系统的树结构,树中

有所有文件和目录的元数据信息。这些信息以两种形式保存在本地磁盘上:命名空间镜像

和编辑日志。namenode也知道给定的文件的所有block在哪个datanode上;但是,它不存

储block地址,因为这个信息在系统重启后会被重新构造。

客户端通过与namenode和datanode交互来代表用户访问文件系统。客户端提供了一个

文件系统接口,与可移植操作系统接口相似,所以用户函数不需要知道namenode和datanode。

datanode是文件系统中干重活的。他们存储、搜索block(当客户端或namenode让它去做时),

它周期性向namenode汇报它所存储的block列表。

没有namenode,文件系统就无法使用。事实上,如果机器的namenode被消除,它上面的

文件系统中的所有文件都会丢失,因为无法根据datanode上的block来知道如何重构文件。基

于这个原因,让namenode可以从故障中恢复是很重要的,HADOOP为它提供了两种方法。

第一种方式是备份存有文件系统元数据的持久状态的文件。HADOOP可以配置来把它的

namenode的持久状态写到不同的文件系统。这些写入是同步的并且是原子操作。通常的配

置选择是写到本地文件系统,同时写到网络文件系统。

也可以运行一个secondary namenode,它是名不符实的,和namenode并不一样。它的主

要职责是合并命名空间镜像和编辑日志以防止它变的太过巨大。secondary namenode通常

运行在一个单独的机器上,因为它需要大量的CPU以及和namode一样多的内存来执行合并。

它保存了要合并的命名空间镜像的一个副本,它可以在namenode故障时使用。尽管如此,

secondary namenode相对于namenode有延迟,所以一旦彻底故障,几乎可以肯定会有

数据丢失。这种情况下通常的做法是把网络文件系统的元数据文件拷贝到secondary namenode

上做为namenode运行(注意,可以运行一个热备份namenode来取代secondary,见

48页“HDFS高可用性“)。

查看318页“文件系统镜像及编辑日志”以了解更多。

block缓存

通常datanode从磁盘读取block,但对于经常访问的文件,它的block可能会缓存在

datanode的内存里,即非堆block cache。默认情况下,一个block只缓存在一个

datanode的内存中,尽管这个数量是可配置的。job安排者(MapReduce,Spark以及

其它一些框架)可以复用缓存的block在对应的datanode上运行task,来提高读取效率。

例如,关联中用到的一个小的表是使用缓存的一个很好的选择。

用户或应用程序通过对缓冲池添加缓冲指令来指导namenode缓存哪个文件(以及缓存

多久)。缓冲池是用来管理缓冲许可及资源使用的。

HDFS联合

namenode在内存中保存了文件系统中所有文件和block的引用,它意味着在有许

多文件的大型集群中,内存将成为规模扩大的限制(见294页“一个namenode需要

多少内存“)。HDFS联合,在2.x版本中引入,允许通过增加namenode来扩大规模,

每一个namenode管理一部分文件系统例句空间。例如,一个namenode可能管理

/user下的所有文件,另一个namenode管理/share下的所有文件。

在联合中,每一个namenode管理一个namespace volume,它由namespace的

元数据组成,以及一个block pool,它包含namespace中文件对应的所有block。

namespace volume是彼此独立的,它意味着namenode之间不会相互交互,一个

namenode失效不会影响别一个namenode管理的namespace的使用。

访问HDFS联合集群,客户端使用表来映射文件路径到namenode。这个是

使用ViewFileSystem和viewfs://URIs来配置管理的。

HDFS HA(高可用性)

结合使用namenode元数据复制到不同的文件系统及使用secondary namenode来

创建检查点来防止数据丢失并没有提供文件系统的高可用性。namenode依然是单点

失败的。如果它发生故障,所有的客户端----包括MapReduce job----也不能读取、写入

或查看文件,因为只有namenode保存了元数据以及文件到block的映射关系。在这种情况下

整个HADOOP系统都陷入瘫痪,直到一个新的namenode上线。

为了从故障中恢复,管理员要开启一个新的namenode,提供文件系统元数据复件

并配置datanode和客户端使用这个新的namenode。新的namenode不能处理请求直到:

(i)把它的namespace image加载进内存,

(ii)替换它的编辑日志,

(iii)得到足够的datanode中的block报告以结束安全模式。一个含有许多文件和

block的庞大集群,namenode启动要花费30分钟甚至更多。

恢复时间过长对于日常维护也是一个问题。事实上,namenode意料外的故障很少见,

在实践中,有针对故障停机的计划是非常重要的。

HADOOP2通过支持HDFS高可用来补救这个问题。在这个实现中,有一对处于主

备模式的namenode。一旦主namenode发生故障,备用的无缝接替它的职责继续

为客户端服务。需要改变一些架构来支持它:

  • namenode必须使用高可用的共享存储来共享编辑日志。当备用namenode开启后,它读取共享的编辑日志,

使自己的状态与主namenode同步,然后继续读取主namenode写的记录。

  • datanode必须同时发送报告给主备namenode,因为block映射保存在namenode的内存中,而不是磁盘上。
  • 客户端必须被配置以应对namenode故障切换,使用一个对用户透明的机制来实现。
  • secondary namenode的职责被包含在备份namenode中,即周期检查主namenode的namespace。

高可用共享存储有两个选择:一个是NFS filer,一个QJM(quorum journal manager)。

QJM是针对HDFS的实现,设计专门用来提供高可用编辑日志,大部分HDFS安装推荐使用它。

QJM运行像一组journal node,每一个编辑必须写到一个主journal node。典型的,有三个

journal node,所以系统可以容忍其中一个发生故障。它和zookeeper的工作方式差不多,

但是必须要清楚QJM的实现并没有使用zookeeper(然而,HDFS HA确实使用了zookeeper

来选择active namenode,在下一节会讲到)。

如果active namenode失效,standby(namenode)可以很快接管它的工作(在几十秒内)

因为在内存中有最新的状态:包括最新的编辑日志和最近的block映射。在实际中故障转移所

用时间要长一些(大约一分钟),因为系统需要小心确认active namenode是否真的发生故障了。

万一当active发生故障而standby还是关机状态时,管理员也可以开启standby。这不会比

non-HA的状况更糟,而且从可操作这个点来说它是一个进步,因为这个流程作为一个标准

操作步骤内置进了HADOOP。

Failover和fencing

active namenode过渡到standby的过程由系统中一个叫failover controller的控制器来管理。

有许多种failover controller,但是默认的实现是使用zookeeper来保证只有一个namenode是

active的。每一个namenode都运行一个轻量级的failover controller,它的工作就是监视它的

namenode是否发生故障(使用最简单的心跳机制)并且在namenode发生故障时触发failover。

failover也可以由管理员发起,例如,日常维护。这就是graceful failover,因为failover controller

管理两个namenode有序过渡来切换角色。

在ungraceful failover情况下,不能确定故障namenode是否真的停止工作了。如,

一个缓慢的网络工作可能触发failover,尽管前一个acitve namenode还在运行,并自认为还是

active namenode。HA竭尽全力确保前一个active namenode不会产生破坏----通过一个被称为

fencing的方法。

QJM在同一时刻只允许一个namenode修改编辑日志;尽管如此,前一个acitve namenode

还是有可能对客户端产生脏读,所以一个好的方法是设置一个SSH fencing命令,它会杀死

namenode进程。当使用NFS filer来共享edit log时需要更强大的fencing方法,因为它不可能

在同一时间只允许一个namenode执行写操作(这是为什么推荐使用QJM的原因)。fencing

机制包含撤消namenode访问共享存储目录(一般使用特定平台的NFS命令),以及通过远程

管理命令来禁止它的网络端口。作为最后一个手段,可以使用STONITH技术来达到fence前一个

active namenode的目的,也就是“shoot the other node in the head”,它使用一个专门的配电

装置来强制关掉主机。

客户端failover由客户端库控制。最简单的实现是使用客户端的配置文件来控制failover。

HDFS URI使用逻辑主机名称来映射到那两个namenode的地址(在配置文件中),客户端

连接每一个namenode地址直到操作成功。

时间: 2024-08-03 19:02:28

第三章 第二节 HDFS概念的相关文章

【软件构造】第三章第二节 设计规约

第三章第二节 软件规约 这一节我们转向关注"方法/函数/操作"是如何定义的,即讨论编程中的动词,规约. Outline 一个完整的方法 什么是设计规约,我们为什么需要他 行为等价性 规约的结构:前置条件与后置条件 规约的结构 可变方法的规约 规约的评价 规约的确定性 规约的陈述性 规约的强度 如何设计一个好的规约 是否使用前置条件 Notes ## 一个完整的方法 一个完整的方法包括规约spec和实现体implementation: "方法"是程序的积木,它可以被独

软件构造 第三章第二节 软件规约

第三章第二节 软件spec 客户端无需阅读调用函数的代码,只需理解spec即可. 精确的规约,有助于区分责任,给"供需双方"确定了责任,在调用的时候双方都要遵守. @param @return @throws 例子: Behavioral equivalence (行为等价性) 根据规约判断是否行为等价 与实现无关! 如果两个函数符合这个规约,故它们等价. Specification Structure 前置条件(precondition):对客户端的约束,在使用方法时必须满足的条件.

【软件构造】第五章第二节 设计可复用的软件

第五章第二节  设计可复用的软件 5-1节学习了可复用的层次.形态.表现:本节从类.API.框架三个层面学习如何设计可复用软件实体的具体技术. Outline 设计可复用的类--LSP 行为子结构 Liskov替换原则(LSP) 各种应用中的LSP 数组是协变的 泛型中的LSP 为了解决类型擦除的问题-----Wildcards(通配符) 设计可复用的类--委派与组合 设计可复用库与框架 Notes ## 设计可复用的类--LSP 在OOP之中设计可复用的类 封装和信息隐藏 继承和重写 多态.子

【软件构造】第六章第二节 可维护的设计模式

第六章第二节 可维护的设计模式 Outline 创造性模式:Creational patterns 工厂模式(Factory Pattern) 抽象工厂模式(Abstract Factory Pattern) 建造者模式(Builder Pattern) 结构化模式:Structural patterns 桥接模式(Bridge Pattern) 代理模式(Proxy Pattern) 组合模式(Composite Pattern) 行为化模式:Behavioral patterns 中介者模式

Git帮助文档阅读笔记----第二章-第二节

查看提交历史 1.查看提交历史 git log 默认不用任何参数的话,git log 会按提交时间列出所有的更新,最近的更新排在最上面 git log 有许多选项可以帮助你搜寻感兴趣的提交 1.  -p选项展开显示每次提交的内容差异 2.  -2显示最近的两次更新 该选项除了显示基本信息之外,还在附带了每次 commit 的变化.当进行代码审查,或者快速浏览某个搭档提交的 commit 的变化的时候,这个参数就非常有用了. 某些时候,单词层面的对比,比行层面的对比,更加容易观察.Git 提供了 

【软件构造】第二章第二节 软件构造的过程、系统和工具

第二章第二节 软件构造的过程.系统和工具 Outline 广义的软件构造过程 编程 静态代码分析 动态代码分析 调试与测试 重构 狭义的软件构造过程 构造系统:经典BUILD场景 构造系统的组件 构造过程和构造描述 Java编译工具 子目标和结构变体 构造工具 Notes ## 广义的软件构造过程 [编程(Coding)] 开发语言:如Java.C.Python 使用IDE(集成开发工具)的优势(组成) 方便编写代码和管理文件(有代码编辑器,代码重构工具.文件和库(Library)管理工具) 能

【软件构造】第七章第二节 错误与异常处理

第七章第二节 错误与异常处理 本节关注:Java中错误和异常处理的典 型技术--把原理落实到代码上! Outline: Java中的错误和异常(java.lang.throwable) 异常 Runtime异常与其他异常(Exception) Checked异常和unchecked异常 checked异常的处理机制 自定义异常 Notes: ## Java中的错误和异常 [Throwable] Java.lang.throwable Throwable 类是 Java 语言中所有错误或异常的超类

软件构造 第一章第二节 软件开发的质量属性

?软件构造 第一章第二节 软件开发的质量属性 1.软件系统质量指标 External quality factors affect users 外部质量因素影响用户 Internal quality factors affect the software itself and its developers 内部质量因素影响软件本身和它的开发者 External quality results from internal quality 外部质量取决于内部质量 外部属性: 正确性:按照预先定义的"

软件构造 第七章第二节 错误与异常处理

第七章第二节 错误与异常处理 内部错误:程序员通常无能为力,一旦发生,想办法让程序优雅的结束 异常:你自己程序代码发生的,可以捕获处理 [Error] Error类描述很少发生的Java运行时系统内部的系统错误和资源耗尽情况(例如,VirtualMachineError,LinkageError). 对于内部错误:程序员通常无能为力,一旦发生,想办法让程序优雅的结束 Error的类型: 用户输入错误 例如:用户要求连接到语法错误的URL,网络层会投诉. 设备错误 硬件并不总是做你想做的. 输出器