亲宝软件园·资讯

展开

大数据篇:HDFS

咘雷扎克 人气:2

HDFS

HDFS是什么?

Hadoop分布式文件系统(HDFS)是指被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统(Distributed File System)。它和现有的分布式文件系统有很多共同点。但同时,它和其他的分布式文件系统的区别也是很明显的。HDFS是一个高度容错性的系统,适合部署在廉价的机器上。HDFS能提供高吞吐量的数据访问,非常适合大规模数据集上的应用。HDFS放宽了一部分POSIX约束,来实现流式读取文件系统数据的目的。HDFS在最开始是作为Apache Nutch搜索引擎项目的基础架构而开发的。HDFS是Apache Hadoop Core项目的一部分。

如果没有HDFS!

  1. 大文件的储存我们必须要拓展硬盘。
  2. 硬盘拓展到一定的量以后,我们就不能在一个硬盘上储存文件了,要换一个硬盘,这样文件管理就成了问题。
  3. 为了防止文件的损坏吗,我们需要创建副本,副本的管理也成了问题。
  4. 分布式计算非常麻烦。

1 HDFS出现原因

1.1 早期文件服务器

  • 从上图中,我们可以看出,存储一个文件,我们一直往一个机子上面存是不够的,那么我们在储存量不够的时候就会加机子。
  • 但是如果一个文件放在一台机子上,如果该机器挂了,那么文件就丢失了,不安全。
    所以我们会把一个文件放在多台机子上,创建一个索引文件来储存文件的指针,如图中的file1存储在node1,node2,node3上面,以此类推
  • 缺点:
    • 难以实现负载均衡
      • 文件大小不同,负载均衡不易实现
      • 用户自己控制文件大小
    • 难以并行化处理
      • 只能利用一个节点资源处理一个文件
      • 无法动用集群资源处理同一个文件

1.2 HDFS文件服务器

  • HDFS前提和设计目标
    • 存储超大文件
      • HDFS适合存储大文件,单个文件大小通常在百MB以上
      • HDFS适合存储海量文件,总存储量可达PB,EB级
    • 硬件容错
      • 基于普通机器搭建,硬件错误是常态而不是异常,因此错误检测和快速、自动的恢复是HDFS最核心的架构目标
    • 流式数据访问
      • 为数据批处理而设计,关注数据访问的高吞吐量
    • 简单的一致性模型
      • 一次写入,多次读取
      • 一个文件经过创建、写入和关闭之后就不需要改变
      • 如果是update操作其实是增加了版本号,并没有修改源文件
    • 本地计算
      • 将计算移动到数据附近(数据在哪个节点就在哪里计算)

  • 从上图我们看出,HDFS是把一个大的数据,拆成很多个block块,然后在将block存储在各个机子上。
    创建文件对应block的指针文件,和block对应的节点node的指针文件。
  • 源自于Google的GFS论文
    • 发表于2003年10月
    • HDFS是GFS克隆版
    • 易于扩展的分布式文件系统
    • 运行在大量普通廉价机器上,提供容错机制
    • 为大量用户提供性能不错的文件存取服务

1.3 HDFS优缺点

  • 优点
    • 高容错性
      • 数据自动保存多个副本
      • 副本丢失后,自动恢复
    • 适合批处理
      • 移动计算而非数据
      • 数据位置暴露给计算框架
    • 适合大数据处理
      • GB、TB、甚至PB级数据
      • 百万规模以上的文件数量
      • 10K+节点规模
    • 流式文件访问
      • 一次性写入,多次读取
      • 保证数据一致性
    • 可构建在廉价机器上
      • 通过多副本提高可靠性
      • 提供了容错和恢复机制
  • 缺点
    • 低延迟数据访问(慢)
      • 比如毫秒级
      • 低延迟与高吞吐率
    • 小文件存取
      • 占用NameNode大量内存
      • 寻道时间超过读取时间
    • 并发写入、文件随机修改
      • 一个文件只能有一个写者
      • 仅支持append(追加)
  • 适用场景:适合一次写入,多次读出的场景,支持追加数据且不支持文件的修改。

1.4 基本构成

  • 数据块
    • 文件以块为单位进行切分存储,块通常设置的比较大(最小6M,默认128M),根据网络带宽计算最佳值。
    • 块越大,寻址越快,读取效率越高,但同时由于MapReduce任务也是以块为最小单位来处理,所以太大的块不利于于对数据的并行处理。
    • 一个文件至少占用一个块(如果一个1KB文件,占用一个块,但是占用空间还是1KB)
    • 我们在读取HDFS上文件的时候,NameNode会去寻找block地址,寻址时间为传输时间的1%时,则为最佳状态。
      • 目前磁盘的传输速度普遍为100MB/S
      • 如果寻址时间约为10ms,则传输时间=10ms/0.01=1000ms=1s
      • 如果传输时间为1S,传输速度为100MB/S,那么一秒钟我们就可以向HDFS传送100MB文件,设置块大小128M比较合适。
      • 如果带宽为200MB/S,那么可以将block块大小设置为256M比较合适。
  • Namenode(master管理者)
    • 管理HDFS的文件树及名称空间
    • 数据复制策略
    • 管理数据块(Block)的映射信息
    • 处理客户端读写请求。
  • Datanode(slave实际操作者)
    • 存储实际的数据块
    • 执行数据块的读写请求
  • Client(客户端)
    • 文件切分,上传HDFS时,将文件切分成一个一个Block,然后进行上传。
    • 与Namenode交互,获取文件位置信息。
    • 与Datanode交互,读取或者写入数据。
    • 提供API来管理HDFS。
  • SecondaryNameNode
    • 并非是NameNode的热备,当NameNode挂掉的时候,它并不能马上替换NameNode并提供服务。
    • 辅助NameNode,比如根据检查点,定期合并Fsimage和Edits,并推送给NameNode。

1.5 所处角色

2 HDFS物理网络环境(集群结构)

  • 比较重要服务功能最好能部署在不同的节点上,如:NN。
  • 不重要的可以在一个节点上,如:DN。
  • 副本选择机制:当副本为3的时候,第一个为本地最近的节点,第二个为同机架的不同节点,第三个为不同机架的不同节点。

3 HDFS 读写工作原理

3.1 HDFS文件写入流程

  1. 客户端创建 DistributedFileSystem 对象.
  2. DistributedFileSystem 对象调用元数据节点,在文件系统的命名空间中创建一个新的文件,元数据节点首先确定文件原来不存在,并且客户端有创建文件的权限,然后创建新文件,并标识为“上传中”状态,即可以看见,但不能使用。
  3. DistributedFileSystem 返回 DFSOutputStream,客户端用于写数据。
  4. 客户端开始写入数据,DFSOutputStream 将数据分成块,写入 data queue(Data queue 由 Data Streamer 读取),并通知元数据节点分配数据节点,用来存储数据块(每块默认复制 3 块)。分配的数据节点放在一个 pipeline 里。Data Streamer 将数据块写入 pipeline 中的第一个数据节点。第一个数据节点将数据块发送给第二个数据节点。第二个数据节点将数据发送给第三个数据节点。注意:并不是第一个数据节点完全接收完 block 后再发送给后面的数据节点,而是接收到一部分 就发送,所以三个节点几乎是同时接收到完整的 block 的。DFSOutputStream 为发出去的数据块保存了 ack queue,等待 pipeline 中的数据节点告知数据已经写入成功。如果 block 在某个节点的写入的过程中失败:关闭 pipeline,将 ack queue 放 至 data queue 的开始。已经写入节点中的那些 block 部分会被元数据节点赋予新 的标示,发生错误的节点重启后能够察觉其数据块是过时的,会被删除。失败的节点从 pipeline 中移除,block 的其他副本则写入 pipeline 中的另外两个数据节点。元数据节点则被通知此 block 的副本不足,将来会再创建第三份备份。
  5. ack queue 返回成功。
  6. 客户端结束写入数据,则调用 stream 的 close 函数,
  7. 最后通知元数据节点写入完毕
  • 总结:

    客户端切分文件 Block,按 Block 线性地和 NN 获取 DN 列表(副本数),验证 DN 列表后以更小的单位流式传输数据,各节点两两通信确定可用,Block 传输结束后,DN 向 NN 汇报 Block 信息,DN 向 Client 汇报完成,Client 向 NN 汇报完成,获取下一个 Block 存放的 DN 列表,最终 Client 汇报完成,NN 会在写流程更新文件状态。

3.2 HDFS文件读取流程

  1. 客户端(client)用 FileSystem 的 open()函数打开文件。
  2. DistributedFileSystem 调用元数据节点,得到文件的数据块信息。对于每一个数据块,元数据节点返回保存数据块的数据节点的地址。
  3. DistributedFileSystem 返回 FSDataInputStream 给客户端,用来读取数据。
  4. 客户端调用 stream 的 read()函数开始读取数据(也会读取 block 的元数据)。DFSInputStream 连接保存此文件第一个数据块的最近的数据节点(优先读取同机架的 block)。
  5. Data 从数据节点读到客户端。当此数据块读取完毕时,DFSInputStream 关闭和此数据节点的连接,然后连接此文件下一个数据块的最近的数据节点。
  6. 当客户端读取完毕数据的时候,调用 FSDataInputStream 的 close 函数。
  7. 在读取数据的过程中,如果客户端在与数据节点通信出现错误,则尝试连接包含此数据块的下一个数据节点。失败的数据节点将被记录,以后不再连接。
  • 总结:

    客户端和 NN 获取一部分 Block(获取部分 block 信息,而不是整个文件全部的 block 信 息,读完这部分 block 后,再获取另一个部分 block 的信息)副本位置列表,线性地和 DN 获取 Block,最终合并为一个文件,在 Block 副本列表中按距离择优选取,如果选取到的副本完整就返回,否则找下一个副本。

4 深入

4.1 NameNode和SecondaryNameNode

  • 作用:
    • Namespace管理:负责管理文件系统中的树状目录结构以及文件与数据块的映射关系
    • 块信息管理:负责管理文件系统中文件的物理块与实际存储位置的映射关系BlocksMap
    • 集群信息管理:机架信息,datanode信息
    • 集中式缓存管理:从Hadoop2.3 开始,支持datanode将文件缓存到内存中,这部分缓存通过NN集中管理
  • 存储结构:
    • 内存: Namespace数据,BlocksMap数据,其他信息
    • 文件:
      • 已持久化的namespace数据:FsImage
      • 未持久化的namespace操作:Edits

合并流程:

  1. NN 创建一个新的 edits log 来接替老的 edits 的工作
  2. NN 将 fsimage 和旧的 edits 拷备到 SNN 上
  3. SNN 上进行合并操作,产生一个新的 fsimage
  4. 将新的 fsimage 复制一份到 NN 上
  5. 使用新的 fsimage 和新的 edits log

4.2 集群启动过程

  1. 开启安全模式:不能执行数据修改操作

  2. 加载fsimage

  3. 逐个执行所有Edits文件中的每一条操作将操作合并到fsimage,完成后生成一个空的edits文件

  4. 接收datanode发送来的心跳消息和块信息

  5. 根据以上信息确定文件系统状态

  6. 退出安全模式

4.3 安全模式

  • 安全模式:文件系统只接受读数据请求,而不接受删除、修改等变更请求
  • 什么情况下进入:NameNode主节点启动时,HDFS进入安全模式
  • 什么时候时候退出:系统达到安全标准时,HDFS退出安全模式
    • dfs.namenode.safemode.min.datanodes: 最小可用datanode数量
    • dfs.namenode.safemode.threshold-pct: 副本数达到最小要求的block占系统总文件block数的百分比
      • 总文件block数100个,每个block需要有3个副本,满足3个副本的block数量为70个,那么pct=70%(默认0.999)
      • 常见进入安全模式不退出就是因为学习机器不够,副本数低于3,这个参数进行验证不通过。
    • dfs.namenode.safemode.extension: 稳定时间
  • 相关命令:
    • hdfs dfsadmin -safemode get:查看当前状态
    • hdfs dfsadmin -safemode enter:进入安全模式
    • hdfs dfsadmin -safemode leave:强制离开安全模式
    • hdfs dfsadmin -safemode wait:一直等待直到安全模式结束

5 HDFS Federation (联邦)

通过多个 namenode/namespace 把元数据的存储和管理分散到多个节点中,使到namenode/namespace 可以通过增加机器来进行水平扩展。能把单个 namenode 的负载分散到多个节点中,在 HDFS 数据规模较大的时候不会也降低 HDFS 的性能。可以通过多个namespace 来隔离不同类型的应用,把不同类型应用的 HDFS 元数据的存储和管理分派到不同的 namenode 中。核心:多台 namenode 管理的是同一个集群!

假设服务器内存:128G=137438953472字节 ,一个块大概使用150字节,那么可以存储的块数量为:916259689g个,因为一个默认块大小为128M,那么可以储存的文件大小为109PB左右,远远达不到大数据的规模(目前有些大公司能达到一台NameNode管理上EB的数据),这个时候就需要Federation(联邦),多个NameNode管理一套集群。

6 HDFS HA(High Availability高可用)

6.1 高可用架构图

  • 主备 NameNode,解决单点故障:
    • ANN:ActiveNameNode,对外提供服务,SNN 同步 ANN 元数据,以待切换。
    • SNN:StandbyNameNode,完成了 edits.log 文件的合并产生新的 image,推送回 ANN。
    • JNN:JournalNode,ANN 和 SNN 通过 JNN 集群来共享信息。两个 NameNode 为了数据同步,会通过一组称作 JournalNodes 的独立进程进行相互通信。当 ANN 的命名空间有任何修改时,会告知大部分的 JournalNodes 进程。SNN 有能力读取 JNs 中的变更信息,并且一直监控 edit log 的变化,把变化应用于自己的命名空间。SNN 可以确保在集群出错时,命名空间状态已经完全同步了。在 HA 架构里面 SecondaryNameNode 这个冷备角色已经不存在了,为了保持 SNN 实时的与 ANN 的元数据保持一致,他们之间交互通过一系列守护的轻量级进程 JournalNode。基本原理就是用 2N+1 台 JN 存储 editlog,每次写数据操作有超过 半数(>=N+1)返回成功时即认为该次写成功,数据不会丢失了。当然这个算法所能容忍 的是最多有 N 台机器挂掉,如果多于 N 台挂掉,这个算法就失效了。任何修改操作在 ANN上执行时,JN 进程同时也会记录修改 log 到至少半数以上的 JN 中,这时 SNN 监测到 JN 里面的同步 log 发生变化了会读取 JN 里面的修改 log,然后同步到自己的的目录镜像树里面。当发生故障时,ANN 挂掉后,SNN 会在它成为 ANN 前,读取所有的 JN 里面的修改日志,这样就能高可靠的保证与挂掉的 NN 的目录镜像树一致,然后无缝的接替它的职责,维护来自客户端请求,从而达到一个高可用的目的。
    • DN:同时向两个 NameNode 汇报数据块信息(位置)。
  • 两个 NN 之间的切换:
    • 手动切换:通过命令实现主备之间的切换,可以用 HDFS 升级等场合。
    • 自动切换:基于 Zookeeper 实现。
  • HDFS 2.x 提供了 ZookeeperFailoverController 角色,部署在每个 NameNode 的节点上,作为一个 deamon 进程, 简称 zkfc,zkfc 主要包括三个组件:
    • HealthMonitor:监控 NameNode 是否处于 unavailable 或 unhealthy 状态。当前通过RPC 调用 NN 相应的方法完成。
    • ActiveStandbyElector:管理和监控自己在 ZK 中的状态。
    • ZKFailoverController:它订阅 HealthMonitor 和 ActiveStandbyElector 的事件,并管理NameNode 的状态。
      • 简称ZKFC,就是Zookeeper客户端。
      • ZKFailoverController 主要职责:
        • 健康监测:周期性的向它监控的 NN 发送健康探测命令,从而来确定某个NameNode 是否处于健康状态,如果机器宕机,心跳失败,那么 zkfc 就会标记它处于一个不健康的状态
        • 会话管理:如果 NN 是健康的,zkfc 就会在 zookeeper 中保持一个打开的会话,如果 NameNode 同时还是 Active 状态的,那么 zkfc 还会在 Zookeeper 中占有一个类型为短暂类型的 znode,当这个 NN 挂掉时,这个 znode 将会被删除,然后备用的NN,将会得到这把锁,升级为主 NN,同时标记状态为 Active,当宕机的 NN 新启动时,它会再次注册 zookeper,发现已经有 znode 锁了,便会自动变为 Standby状态,如此往复循环,保证高可靠,需要注意,目前仅仅支持最多配置 2 个 NN.
        • master 选举:如上所述,通过在 zookeeper 中维持一个短暂类型的 znode,来实现抢占式的锁机制,从而判断那个 NameNode 为 Active 状态。

6.2 故障转移流程

  • 上图注意:SecondaryNameNode被另一台NameNode取代,edits文件交由qjournal管理。

6.3 CM配置HA注意点:

cdh01.com--------

QuorumPeerMain(zk)

DFSZKFailoverController

NameNode

JournalNode

cdh02.com--------

QuorumPeerMain(zk)

DFSZKFailoverController

JournalNode

DataNode

cdh03.com--------

QuorumPeerMain(zk)

JournalNode

DataNode

7 HDFS纠删码(时间换空间)

  • hdfs3.0后引入纠删码

  • 复制策略:1tb数据,需要3tb磁盘空间
  • 纠删码:只需要复制策略一半左右的磁盘空间,而且同样可以保证数据的可靠性

a=1

b=2

c=3

a+b+c=6

a+2b+3c=14

a+3b+4c=19

我们需要求出a,b,c的值,那么最少需要的方程数为?3个

如果有4个方程,就允许丢失任意一个方程

如果有5个方程,就允许丢失任意两个方程

a=1

b=2

c=3

视为数据

a+b+c=6

a+2b+3c=14

a+3b+4c=19

视为一个效验/沉余数据

如果是复制策略,要允许丢失任意2份数据,我们需要3*3=9份空间

如果是究删码策略,要允许丢失任意2份数据,我们需要3+2=5份空间

8 HDFS文件类型

文件格式 类型 存储方式 是否带schema 特点描述 出处
txt,json,csv 行式 文本 默认存储方式(txt),数据内容可以直接cat查看,存储效率较高,处理效率低。压缩比较低 Hadoop
Sequence file 行式 二进制 以key,value对的方式存储。压缩比中等 Hadoop
Avro 行式 二进制 数据序列化框架,同时支持RPC,数据自带schema,支持比较丰富的数据类型。与protobuf, thrift 类似。压缩比中等 Hadoop
RC(record columnar) 列式 二进制 列式存储,将数据按照行组分块,读取以行组为单位,但是行组中可以跳过不需要的列。压缩比中等 Hive
ORC(optimized record columnar) 列式 二进制 升级版的RC,使用了更优化的存储结构,从而获得更好的性能,另外支持对数据的修改和ACID。压缩比高 Hive
Parquet 列式 二进制 支持嵌套类型,可高效实现对列的查询或统计。压缩比高 Impala

9 数据压缩类型

压缩格式 split 压缩率 压缩速度 是否 hadoop自带 linux命令 换成压缩格式后,原来的应用程序是否要修改 使用建议
gzip 很高 比较快 和文本处理一样,不需要修改 • 使用方便
• 当每个文件压缩之后在130M以内的(1个块大小内),都可以考虑用gzip压缩格式
lzo 比较高 很快 否,需要安装 需要建索引,还需要指定输入格式 • 压缩率和压缩速度综合考虑
• 支持split,是hadoop中最流行的压缩格式;
• 一个很大的文本文件,压缩之后还大于200M以上的可以考虑,而且单个文件越大,lzo优点越明显
• cloudera&twitter
snappy 比较高 很快 否,需要安装 没有 和文本处理一样,不需要修改 • 压缩率和压缩速度综合考虑
• 当mapreduce作业的map输出的数据比较大的时候,作为map到reduce的中间数据的压缩格式
• spark默认压缩格式
• google出品
bzip2 最高 和文本处理一样,不需要修改 • 压缩率高
• 适合对速度要求不高,但需要较高的压缩率,比如数据比较大,需要压缩存档减少磁盘空间并且以后数据用得比较少的情况

10 HDFS常用命令

  1. -help:输出这个命令参数。如:hadoop fs -help ls (输出ls命令的参数)
  2. -ls:显示目录信息。如:hadoop fs -ls / (查询hdfs上根目录的目录,,递归创建加 -R参数)
  3. -mkdir:在hdfs上创建目录。如:hadoop fs -mkdir /haha (根目录下创建haha文件夹,递归创建加 -p参数)
  4. -moveFromLocal:从本地剪切粘贴到hdfs。如:hadoop fs -moveFromLocal /haha/xixi.txt / (将本地haha文件夹下的xixi.txt文件剪切粘贴到hdfs的根目录下)
  5. -copyFromLocal:从本地拷贝到hdfs上。如:用法同上
  6. -copyToLocal:从hdfs上拷贝到本地。如:用法同上
  7. -cp:从hdfs的一个路径拷贝到hdfs的另一个路径。如:方法同上
  8. -mv:从hdfs上的一个路径移动到hdfs的另一个路径。如:方法同上
  9. -appendToFile:追加一个文件到已经存在的文件末尾。如:hadoop fs -appendToFile /haha/lala.txt /xixi.txt (将本地lala.txt文件内容追加到hdfs上xixi.txt里)
  10. -cat:显示文件内容。如:hadoop fs -cat /xixi.txt (查看xixi.txt)
  11. -tail:显示一个文件的末尾。
  12. -chmod:修改文件权限。如:hadoop fs -chmod 777 /xixi.txt (修改xixi.txt文件的权限)
  13. -get:等同于copyToLocal,就是从hdfs下载文件到本地。如:hadoop fs -get /xixi.txt ./ (下载到当前本地路径)
  14. -getmerge:合并下载多个文件,如:hadoop fs -getmerge /log/*.txt ./sum.txt (将hdfs上log文件夹下的所有.txt文件整合在一起,下载到本地,名字为sum.txt)
  15. -put:等同于copyFromLocal,就是上传文件到hdfs。如:hadoop fs -put /xixi.txt / (上传到hdfs的根路径)
  16. -rmr:删除文件或目录
  17. -df:统计文件系统的可用空间信息。如:hadoop fs -df -h /
  18. -du:统计文件夹的大小信息。如:-s总大小、-h单位
  19. -count:统计一个指定目录下的文件节点数。如:结果2 2 199 (第一个参数说的是最多有几级目录,第二个参数说的是一共有多少文件)

11 HDFS SHELL操作

11.1 hdfs常用基础命令

  • 帮助:hadoop fs -help

  • 查看结构:hdfs dfs -ls [/查看目录名称]

  • 上传:hdfs dfs -put [文件] [/上传目录名称]

  • 拷贝:hdfs dfs -cp [源文件名] [目标文件名]

  • 查看文件:hdfs dfs -cat [文件名]

  • 删除:hdfs dfs -rmr [文件]

  • 修改权限(同linux):hdfs dfs -chmod [权限级别] [文件]

  • 查看硬盘:hdfs dfs -df -h

  • 查看每个文件占用大小:hdfs dfs -du -h [目录]

11.2 本地->HDFS命令

  • 上传:hdfs dfs -put [文件] [/上传目录名称]

  • 上传(同put):hdfs dfs -copyFromLocal [文件] [/上传目录名称]

  • 剪切上传:hdfs dfs -moveFromLocal [文件] [/上传目录名称]

  • 追加:hdfs dfs -appendToFile [源文件] [/需要追加的文件]

11.3 HDFS->本地命令

  • 下载:hdfs dfs -get [/HDFS源文件] [本地路径]

  • 下载(同get):hdfs dfs -copyToLocal [/HDFS源文件] [本地路径]

  • 合并下载:hdfs dfs -getmerge [/HDFS源文件] [本地文件名]

11.4 合并小文件

  • 打包:hadoop archive -archiveName [har包名称] -p [/需要打包文件] [/打包文件存放地址]

  • 查看包:hdfs dfs -ls har://[har包文件]

12 windows 大数据开发环境配置

  1. 下载winutils解压
  2. 配置对应版本的环境变量名为:HADOOP_HOME 值为:解压目录如上F:\bigdatasoft\hadoop\winutils-master\hadoop-3.0.0
  3. 环境变量Path添加:%HADOOP_HOME%\bin
  4. 重启电脑,打开cmd,输入winutils,出现下图证明配置成功


13 基本API使用

项目地址:https://github.com/70416450/Bigdata-Util

  • 修改hdfs.properties中的配置信息
  • 使用单元测试类测试每一个API吧。

加载全部内容

相关教程
猜你喜欢
用户评论