对Hadoop生态的认识

282 阅读11分钟

在大数据领域,Hadoop几乎是一个绕不开的名词,最近又重读了《Hadoop权威指南》,这篇文章总结下我对Hadoop生态的认识。

1. 数据存储与分析处理

我们知道,多年来硬盘的存储容量一直在不断地提升,但是硬盘的传输速率却一直没有得到飞跃式的提高,因此在对大容量的硬盘进行读写时,其时长是难以接受的。

为了减少数据读写时长,人们想到可以同时从多个硬盘上进行数据读写。比如从100个硬盘上,每个硬盘都存储1%的数据,并行读取,就可以在很短的时间内读取完成。

但是为了对多个硬盘进行并行数据读写,有两个主要的问题:

  • 如何管理多个硬盘对数据进行存储?
  • 如何对来自多个硬盘的数据进行分析和处理?

为了解决这些问题,Apache就提供了一个可靠的共享存储和分析系统,即Hadoop。

简单地说,Hadoop就是把计算机集群环境中的多台计算机在逻辑上统一为一台计算机,使之远超过一台高性能计算机的存储和计算能力。在具备处理特大量级数据的能力的同时,也降低了硬件成本。

2. Hadoop

Hadoop是一个由Apache基金会所开发的分布式系统基础架构, 是一个存储+计算的软件框架,其核心就是HDFS和MapReduce。

(1) HDFS

HDFS是Hadoop分布式文件系统,该系统架构于网络之上,比普通磁盘文件更为复杂。

1) 数据块

HDFS的物理存储单位是块(blcok),但是比一般磁盘的数据块大小(512字节)大得多,默认为64MB或128MB。

HDFS中的块为什么要设置这么大呢?

设置这么大的原因,是为了最小化寻址开销。

如果块足够大,从磁盘传输数据的时间就会明显大于定位这个块开始位置所需要的时间。

因此,传输一个由多个块组成的文件的时间取决于磁盘传输速度。

但是块也不会设置的过大,因为MapReduce中的map任务通常一次只处理一个块中的数据,因此如果任务数太少,作业的运行速度就会比较慢。

HDFS对这些块进行了抽象,有以下三点好处:

  • 一个文件的大小可以大于网络中任意一个磁盘的容量,也就是说文件的所有块并不需要存储在同一个磁盘上;
  • 使用抽象块可以简化存储子系统的设计;
  • 块非常适合用于数据备份进而提供数据容错能力和提高可用性。

2) 节点

HDFS中的一个节点就是计算机集群中的某一台计算机。

HDFS中有两类节点,命名节点(Namenode)和数据节点(Datanode)。

Namenode维护着文件系统树以及树内所有的文件和目录,它记录着每个文件中各个块所在的Datanode信息,保存文件系统中每个文件和每个数据块的映射。

Datanode用来存储数据,并定期向Namenode发送它们所存储的块的信息。

在读取数据时,Namenode告知客户端该文件每个块中最佳的Datanode,并让客户端直接连接到该Datanode检索数据;在写入数据时,客户端先在Namenode上为创建新文件写入一条新纪录,然后再写入Namenode所分配的一组Datanode中,这一组Datanode就构成了一个管线。

3) 高扩展性

HDFS在2.x发行版本中引入的联邦HDFS,允许通过添加Namenode来实现扩展,其中每个Namenode管理文件系统命名空间中的一部分。比如,一个Namenode管理/user目录下的所有文件,另一个Namenode管理/share目录下的文件。

4) 高可用性

HDFS通过对Namenode备份来增加对高可用性的支持。

当活动的Namenode失效,备用的Namenode就会接管它的任务并开始服务来自客户端的请求,不会有明显的中断。

(2) MapReduce

MapReduce是一种计算框架,是一种可用于数据处理的编程模型,该模型抽象出这些硬盘读写问题并将其转换为对一个数据集的计算,这样的计算由map和reduce两阶段组成,每个阶段都以键值对作为输入和输出。

Map阶段可以理解为对数据的准备阶段,它以原始数据为输入,输出的结果写入本地硬盘;
Reduce阶段可以理解为对数据的汇总阶段,它以Map的输出作为输入,输出的结果写入HDFS中。

MapReduce相比传统的关系型数据库系统(RDBMS)的区别在哪呢?

  • MR适合以批处理的方式处理需要分析整个数据集的问题,RDBMS适用于点查询和更新
  • MR适合一次写入、多次读取数据的应用,RDBMS则更适合持续更新的数据集
  • MR适合操作非结构化或半结构化数据,RDBMS往往用来处理结构化数据 image.png

那该如何实现MapReduce呢?

要实现一个简单的MR需要三样东西:一个map函数、一个reduce函数以及一些用来运行作业的驱动程序。

实际上,Hadoop可以运行各种语言版本的MapReduce程序,比如Java、Ruby、Python、C++等等。

比如在Java中,Apache提供了一些类或接口,可以通过实现接口或继承类来编写map和reduce函数。然后在main方法中,通过Job来指定作业执行规范,也就是设置map和reduce函数所在的类,最终执行作业即可。

(在不同的Hadoop版本中,其API有所不同,要注意分别。)

可以通过单元测试,使用小数据集来确保函数的运行符合预期结果,然后再放到集群上运行。最后,可以通过任务剖析,进行一些优化调整,提高MapReduce程序的运行速度。

3. Yarn

在经典的MapReduce中,当节点数过多时,就开始面临扩展性的瓶颈,于是Yarn就应运而生了。(我们上边提到的HDFS的高扩展和高可用,就是Yarn的功劳)

Yarn是Yet Another Resource Negotiator的简称,即另一种资源协调者。它是一种新的Hadoop资源管理器,也可以称为MapReduce 2。

在经典的MapReduce中,有四种实体:

  • 客户端:用于提交MapReduce作业;
  • jobtracker:它是一个Java应用程序,用于协调作业的运行,包括资源管理和作业调度;
  • tasktracker:也是一个Java应用程序,用于执行作业划分后的任务;
  • 分布式文件系统:即HDFS,用于在其他实体间共享作业文件。

而Yarn的核心思想是将实体功能作进一步的划分,所以它包括更多实体:

  • 客户端:用于提交MapReduce作业;
  • 资源管理器(ResourceManager):负责管理和协调集群上所有应用程序计算资源的分配;
  • 节点管理器(NodeManager):管理每个节点上的资源和任务;
  • 应用管理器(ApplicationMaster):每一个应用程序的AM负责协调运行MapReduce作业的任务;它和MapReduce任务在容器中运行,这些容器由资源管理器分配并由节点管理器进行管理;
  • 分布式文件系统:即HDFS,用于在其他实体间共享作业文件。

简单的说,Yarn是一个资源协调者,可以对计算资源进行统一的管理和调度

而计算框架不仅仅只有MapReduce,还有Spark、Flink等等,Yarn也提供对其他计算框架的支持。

4. Spark

如今,在大多数场景,Spark几乎已经替代了MapReduce,成为了最主流的计算框架,最主要有以下两个原因:

(1) RDD 弹性的分布式数据集

RDD(Resilient Distributed Datasets)是弹性分布式数据集,是Spark中最基本的数据抽象,代表一个不可变、可分区、里面的元素可以并行计算的集合。

RDD的概念比较抽象,详细的解释可以看这篇文章

简单地说,Spark建立在抽象的RDD上,使得它可以用一致的方式处理大数据不同的应用场景。通过把所有需要处理的数据转化成RDD,然后对RDD进行一系列的算子运算,从而得到结果。

(2) DAG 有向无环图

Spark使用DAG(有向无环图)来描述RDD之间的依赖关系。

DAG是一组顶点与边的组合,顶点代表RDD,边代表对RDD的一系列操作。

Spark计算模型使用了DAG,目的就是为了优化计算计划,比如减少shuffle和数据落盘的次数。

上边我们说过,MapReduce中map函数的结果会写入本地硬盘,通过牺牲计算性能,减少了内存占用;
而在Spark中,如果计算不涉及与其他节点进行数据交换,Spark可以在内存中一次性完成这些操作。不过如果在计算过程中涉及到了数据交换,Spark也会把shuffle的数据写入磁盘的。

总的来说,Spark是基于内存计算的大数据并行计算框架,它通过DAG优化计算计划,将中间结果保存到了内存中,可以反复利用,提高了处理数据的性能

5. Flink

既然Spark这么好,为什么还需要Flink呢?

这就需要区别下批处理和流处理了:
批处理通常适用于不需要实时分析的场景,处理的是一段时间内收集的大量数据,它可能需要很长时间。
而如果我们需要实时分析结果,处理连续不断的数据集,那么就需要用到流处理。

Spark虽然能进行流处理,但是实时性不够,因此主要还是用于批处理的场景。

而Flink采用了基于操作符的连续流模型,可以做到微秒级别的延迟,时效性高,更适合进行流处理。

6. Hive

我们把数据保存在HDFS中之后,我们需要对这些数据进行查询和计算,但是每次都编写MapReduce程序是很繁琐的,于是Hive就出现了。

Hive是一个构建在Hadoop之上的数据仓库框架,通过HiveSQL(HQL),那些没有编程背景但是掌握SQL技能的人就可以直接对HDFS中的数据进行查询和计算了。

HiveSQL会被转化成MapReduce代码,Hive将这些代码以及相关资源打包成jar并发布到Hadoop的集群中进行执行。

除了HiveSQL,Spark提供的SparkSQL也可以让用户通过编写SQL来对数据进行查询和计算,当然,SparkSQL默认的执行引擎就变成了Spark。

现在,一般会将Spark和Hive结合使用,出现了spark on hive和hive on spark。

spark on hive是指Hive只作为存储角色,Spark负责SQL解析优化和执行,其本质是RDD的形式;
hive on spark是指Hive即作为存储又负责SQL的解析优化,而由Spark负责执行,相当于只是把执行引擎从MapReduce换成了Spark,其余的与Hive是一致的。

目前主要还是使用的是spark on hive的方式。

7. HBase

HBase是一个在HDFS上开发的面向列的非关系型的分布式数据库,它也是常说的NoSQL的一种。

HBase和HDFS是什么关系?有了HDFS为啥还需要HBase?
HDFS只是一个分布式文件系统,它在进行随机访问超大规模数据集时的性能不太好,而HBase可以认为是对HDFS的一个包装,它部署于HDFS之上,可以用于提高查询效率。

Hive作为一种数据仓库,和HBase又有啥区别?
Hive可以认为是对MapReduce的一个包装,完全依赖于HDFS和MapReduce,Hive中的表是纯逻辑表;而HBase中是一个key-value数据库,它的表是物理表。

实际上,Hive和HBase可以同时使用,比如使用Hive来进行统计查询,使用HBase来进行实时查询;数据可以从Hive写入到HBase,也可以从HBase写入Hive,本质上都是存放在HDFS中。

8. ZooKeeper

上边说了,Hadoop是一个分布式系统架构,而分布式应用就必然会有一个问题:一致性问题。

ZooKeeper 是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于ZooKeeper实现诸如数据发布/订阅负载均衡命名服务分布式协调/通知集群管理Master 选举分布式锁分布式队列等功能。

因此,ZooKeeper可以作为Hadoop的分布式协调服务来使用,保证集群节点之间的数据一致性。