一、Hadoop
Hadoop是Apache开源的大数据存储及分析的工具。
-
数据存储
- 以自带的旗舰级分布式文件系统HDFS(Hadoop Distributed FileSystem),存储大数据文件。
-
数据分析
- 基于MapReduce框架的分析系统,适合的问题有
- 需要以批处理的方式从分析整个数据集的问题
- 一次写入,多次读取
- hadoop以数据本地化的特性来实现数据的快速分析。
- 基于MapReduce框架的分析系统,适合的问题有
下图展示的是最基础的Hadoop的框架及常用的周边服务
二、HDFS假设及目标
HDFS是一种高容错、以流式数据访问模式存储超大文件,运行于商用(低成本)硬件集群上。它包含一下假设及目标:
-
节点故障
- Hadoop并不需要运行在昂贵且高可靠的硬件上,它是设计运行在商用硬件(在各种零售商店都能买到的普通硬件)集群上的,因此对于庞大的集群来说节点故障与其说是一个异常不如说是一种正常现象。所以快速监测故障并自动恢复是HDFS的核心架构目标。
-
大文件
- HDFS支持几百MB、几百GB甚至几百TB的文件。
- HDFS的设计思路是一次写入、多次读取是最高效的访问模式,所以一旦文件被创建、写入、关闭后,除了在文件最后追加以及清除文件全部内容之外,其他操作均被禁止。
- 也正是因为大文件的原因Hadoop认为移动计算比移动数据更合适,即计算本地性。
-
流式数据访问
- 流式访问相对于随机访问,只需一次寻址,然后顺序读取数据块。
- HDFS认为每次分析都将涉及到数据集的大部分甚至全部(即批处理,非交互式使用),因此读取整个数据集的时间延迟比读取第一条记录的时间延迟更重要(即强调高吞吐,非低时间延迟访问)。
从上面的假设和目标我们很容易推断出哪些应用不适合在HDFS上运行:
-
低时间延迟的数据访问
- 要求几十毫秒的应用不适合在HDFS上运行。HDFS是为高数据吞吐量应用优化的,这可能会以提高实践延迟为代价。
-
大量的小文件
- 由于namenode将文件系统的元数据存储在内存中,因此文件系统的文件总数受限于namenode的内存容量。因此大量的小文件很可能使得OOM。
-
多用户写入,任意修改文件
- HDFS文件写入只支持单个写入者,并且写操作总是以只添加的方式在文件末尾写数据,不支持多写入、任意位置修改。
三、HDFS基本概念
1 数据块
HDFS将文件划分为不同的块(chunk),作为独立的存储单元,默认为128M(可通过hdfs-site.xml
的dfs.blocksize
属性来修改)。HDFS的块比磁盘的块(512B)大,目的是为了最小化寻址的开销。如果块足够大,从磁盘传输数据的时间会明显大于定位这个块开始位置所需的时间。
对文件进行块的抽象,有以下好处:
- 一个文件的大小可以大于网络中任意一个磁盘的容量
- 简化了存储子系统的设计:块大小固定,计算磁盘能存储的块相对容易,简化管理存储;将块的存储和元数据的存储分离。
- 适用于数据备份进而提供数据容错能力和提高可用性。
2 NameNode和DataNode
HDFS集群有两类节点以master-slaves的模式运行,即一个namenode(master)和多个datanode(slaves)。
namenode
- namenode管理文件系统的命名空间,它维护着文件系统树及整棵树内所有的文件和目录。这些信息以两个文件形式永久保存在本地磁盘:文件系统镜像(FsImage)和编辑日志(EditLog)。
- namenode也记录着每个文件中各个块所在的datanode信息,但它不保存到文件中,而是在内存中,在系统启动时根据datanode的信息重建,并根据datanode发送的心跳信息更新文件块所在的datanode映射关系。
- namenode还负责控制客户端(client)访问文件。客户端通过hadoop披露的文件系统命名空间来进行文件操作。客户端首先向namenode询问文件块所在的datanode,然后连接datanode发送读写的请求。
- namenode分为活动namenode(active namenode),辅助namenode(secondary namenode:负责定期合并FsImage和EditLog(checkpoint),以防止EditLog过大,一般运行在独立的机器上,因为他需要跟namenode同样的内存大小),备用namenode(standby namenode:当主namenode发生故障时可进行热替换)
datanode
- datanode是文件系统的工作节点,存储文件块,并定时向namenode发送他们所存储的块列表。
- 一个文件一般来说会被切分为多个数据块存储到一系列的datanode中。
- datanode还负责块创建、检测、根据namenode的指示创建复本。
下图展示了client、namenode、datanode之间的通信过程。
3 FsImage和EditLog
EditLog
文件系统客户端执行写操作时,这些事务首先会被记录到EditLog中。namenode在内存中维护文件系统元数据,当编辑日志被修改时,相关元数据也同步更新。内存中的元数据可支持客户端的读操作。
EditLog在概念上是单个实体,但它体现为磁盘上的多个文件,
FsImage
每个fsImage文件都是文件元数据的一个完整的永久性检查点。包含了文件系统中的所有目录信息(修改时间、访问许可和配额元数据)和文件信息(复本数、修改时间、访问时间、访问许可、块大小、组成一个文件的块等)的序列化数据。数据块存储在datanode,但fsimage并不描述datanode,取而代之的是namenode将这种块和datanode的映射关系存储在内存中。当datanode加入集群时,namenode向datanode索取块列表以建立块映射关系;namenode还将定时根据datanode上报的信息更新块映射。
fsImage默认存储在
file://${hadoop.tmp.dir}/dfs/name
下,可通过修改dfs.namenode.name.dir
或者hadoop.tmp.dir
的值来更换存储位置
并非每个写操作都会更新该文件,因为fsimage是一个大型文件,如果频繁执行写操作,会使系统运行缓慢。但这不影响系统的恢复能力,当namenode启动或者发生故障重启时,最近的fsimage文件会被load进内存作为构建元数据的最近状态,然后再从相关点开始向前执行EditLog中的每个事务。
为了减少启动时恢复的EditLog事务的时间,HDFS会在辅助namenode或者备用namenode上执行fsimage和EditLog的合并,创建元数据检查点。创建检查点的步骤如下:
- 辅助namenode请求主namenode停止使用正在惊醒的EditLog文件,这样新的编辑日志操作记录到一个新文件中。
- 辅助namenode从主namenode获取最近的fsimage和edits文件(采用HTTP GET)
- 辅助namenode将fsimage文件载入内存,逐一执行edits文件中的事务,创建新的合并后的fsimage文件。
- 辅助namenode将新的fsimage文件发送回主namenode(使用HTTP PUT),主namenode将其保存为临时的.ckpt文件
- 主namenode重新命名临时的fsimage文件,便于日后使用
最终,主namenode拥有最新的fsimage和一个更小的正在进行中的editLog文件。上面的过程也解释了为何辅助namenode需要和主namenode相近的内存需求空间(辅助namenode也需要将fsimage载入内存)。
创建检查点的触发条件收两个参数的控制。
dfs.namenode.checkpoint.period
(单位为秒)来控制时间间隔,dfs.namenode.checkpoint.txns
控制从上一个检查点开始编辑日志的事务个数(检查频率通过dfs.namenode.check.period
来控制)。
在安全模式下也可手动执行
hadoop dfsadmin -saveNamespace
来执行检查点的创建。
4 复本
HDFS将文件的数据块,在不同机器上存储多份(复本)以达到容错。每个文件块的复本个数可以通过dfs.replication
来配置,默认为3。namenode根据内存中的块的映射关系,来决定复本存放的位置。
选择策略:
- 在运行客户端的datanode上房第一个复本(如果客户端运行在集群之外,就随机选择一个节点,但会避免存储太慢或者太忙的节点)
- 第2个复本放在与第一个不同且随机另外选择的机架中节点上
- 第3个复本放在与第二个复本相同的机架上,且随机选择另一个节点
- 其他复本放在集群中随机选择的节点上,不过系统会尽量避免在同一个机架上房太多的复本(最大值为(复本数 - 1 )/机架数 + 2)
一旦选择复本位置,就根据网络拓扑创建一个管线。如果复本数为3,则有如下的管线
5 安全模式
namenode启动时,首先将fsimage文件载入内存,并执行编辑日志的各项编辑操作。一旦在内存中成功建立文件系统的元数据的映像,则创建一个新的fsimage文件和一个空白的EditLog文件。这个过程中,namenode运行在安全模式,意味着namenode文件系统对于客户端是只读的。
在安全模式下,各个datanode会向namenode发送最新的块列表信息,当满足“最小复本条件”,namenode会在30秒后退出安全模式。“最小复本条件”是指整个文件系统中有99.9%的块满足最小复本数,在启动一个刚刚格式化的HDFS集群是,那namenode不会进入安全模式。
- 通过
hdfs dfsadmin -safemode get
来查看是否处于安全模式- 通过
hdfs dfsadmin -safemode enter
进入安全模式- 通过hdfs dfsadmin -safemode leave离开安全模式
安全模式的相关配置如下: