其他分享
首页 > 其他分享> > Hive、Spark、Impala原理阅读笔记

Hive、Spark、Impala原理阅读笔记

作者:互联网

前言-从 Hadoop 说起

什么是 Hadoop

Apache Hadoop 软件库是一个框架,它允许使用简单的编程模型,实现跨计算机集群的大型数据集的分布式处理。它最初的设计目的是为了检测和处理应用程序层的故障,从单个机器扩展到数千台机器(这些机器可以是廉价的),每个机器提供本地计算和存储,而不是依靠硬件提供高可用性。 

Hadoop 中有3个核心组件:

HDFS

HDFS,是 Hadoop Distributed File System 的简称,是 Hadoop 抽象文件系统的一种实现。Hadoop 抽象文件系统可以与本地系统、Amazon S3 等集成,甚至可以通过 Web 协议(webhsfs)来操作。HDFS 的文件分布在集群机器上,同时提供副本进行容错及可靠性保证。例如客户端写入读取文件的直接操作都是分布在集群各个机器上的,没有单点性能压力。传统的文件系统是单机的,不能横跨不同的机器,因此 HDFS 的设计本质上是为了大量的数据能横跨成百上千台机器。即便如此,用户看到的是一个文件系统而不是很多文件系统,比如说要获取 /hdfs/tmp/file1 的数据,引用的是一个文件路径,但是实际的数据存放在很多不同的机器上,作为用户,不需要知道这些,就好比在单机上我们不关心文件分散在什么磁道什么扇区一样,HDFS 为用户管理这些数据。

设计特点

不适用的场景

关键元素

 

基于 HDFS 的数据库

HBase

HBase 是 Hadoop Database 即Hadoop数据库,数据通常存储在 HDFS 上,HDFS 为 HBase 提供了高可靠性的底层存储支持。它是一个适合于非结构化数据存储的数据库,基于列的而不是基于行的模式,同样利用 Hadoop MapReduce 来处理其中的海量数据。

此外,HBase 本身可以完全不考虑 HDFS 的,我们完全可以只把 HBase 当作是一个分布式高并发 k-v 存储系统,只不过它底层的文件系统是通过 HDFS 来支持。换做其他的分布式文件系统也是一样,不影响 HBase 的本质,甚至如果不考虑文件系统的分布式或稳定性等特性,完全可以用简单的本地文件系统,甚至内存文件系统来代替。

使用场景对比

MongoDB

MongoDB 是一种文档数据库,文档是处理信息的基本单位。一个文档可以很长、很复杂,可以无结构,与字处理文档类似。常用于日志的采集和存储,小文件的分布式存储,类似互联网微博应用的数据存储

使用场景

不适合的场景 

MapReduce

HDFS 可以为用户整体管理不同机器上的数据,任务下达时使用很多台机器处理,这就面临了如何分配工作的问题:如果一台机器挂了如何重新启动相应的任务、机器之间如何互相通信交换数据以完成复杂的计算等。这就是 MapReduce 的功能。MapReduce 的设计,采用了很简化的计算模型,只有 Map 和 Reduce 两个计算过程(中间用 Shuffle 串联)。使用这个模型,已经可以处理大数据领域很大一部分问题了。

基本原理

将大的数据分析分成小块逐个分析,最后再将提取出来的数据汇总分析,最终获得我们想要的内容,举例说明:
考虑统计一个存储在 HDFS 上的巨大的文本文件,我们想要知道这个文本里各个词的出现频率。Map阶段,几百台机器同时读取这个文件的各个部分,分别把各自读到的部分分别统计出词频,产生类似(hello, 12100次),(world,15214次)等等这样的 Pair(这里把 Map 和 Combine 放在一起说以便简化);这几百台机器各自都产生了如上的集合,然后又有几百台机器启动 Reduce 处理。Reduce 阶段,Reducer 机器 A 将从 Mapper 机器收到所有以 A 开头的统计结果,机器 B 将收到 B 开头的词汇统计结果(实际上不会真的以字母开头做依据,而是用函数产生 Hash 值以避免数据串化。因为类似 X 开头的词比其他要少得多,会导致各个机器的工作量相差悬殊)。然后这些 Reducer 将再次汇总,(hello,12100)+(hello,12311)+(hello,345881)= (hello,370292)。每个 Reducer 都如上处理,就得到了整个文件的词频结果。
Map+Reduce 的简单模型虽然好用,但是很笨重。第二代的 Tez 和 Spark 除了引入内存 Cache 之类的新 Feature,本质上来说,是让 Map/Reduce 模型更通用,让 Map 和 Reduce 之间的界限更模糊,数据交换更灵活,磁盘的读写更少,以便更方便地描述复杂算法,取得更高的吞吐量。

框架

Hadoop 的集群主要由 NameNode,DataNode,Secondary NameNode,JobTracker,TaskTracker 组成:

 

Hive,Impala 与 Spark

闲谈 Hadoop、Hive、Impala 与 Spark 的关系

”“”

有了 MapReduce,Tez 和 Spark 之后,程序员发现,MapReduce 的程序写起来真麻烦。他们希望简化这个过程。这就好比你有了汇编语言,虽然你几乎什么都能干了,但是你还是觉得繁琐。你希望有个更高层更抽象的语言层来描述算法和数据处理流程。于是就有了 Pig 和 Hive。Pig 是接近脚本方式去描述 MapReduce,Hive 则用的是 SQL。它们把脚本和 SQL语言翻译成 MapReduce 程序,丢给计算引擎去计算,而你就从繁琐的 MapReduce 程序中解脱出来,用更简单更直观的语言去写程序了。
有了 Hive 之后,人们发现 SQL 对比 Java 有巨大的优势。一个是它太容易写了。刚才词频的东西,用 SQL 描述就只有一两行,MapReduce 写起来大约要几十上百行。而更重要的是,非计算机背景的用户终于感受到了爱:我也会写 SQL!于是数据分析人员终于从乞求工程师帮忙的窘境解脱出来,工程师也从写奇怪的一次性的处理程序中解脱出来。大家都开心了。Hive 逐渐成长成了大数据仓库的核心组件。甚至很多公司的流水线作业集完全是用 SQL 描述,因为易写易改,一看就懂,容易维护。
自从数据分析人员开始用 Hive 分析数据之后,它们发现,Hive 在 MapReduce 上跑,真**慢!流水线作业集也许没啥关系,比如24小时更新的推荐,反正24小时内跑完就算了。但是数据分析,人们总是希望能跑更快一些。比如我希望看过去一个小时内多少人在****页面驻足,分别停留了多久,对于一个巨型网站海量数据下,这个处理过程也许要花几十分钟甚至很多小时。而这个分析也许只是你万里长征的第一步,你还要看多少人浏览了**多少人看了******的 CD,以便跟老板汇报,我们的用户是猥琐男闷骚女更多还是文艺青年/少女更多。你无法忍受等待的折磨,只能跟帅帅的工程师蝈蝈说,快,快,再快一点!
于是 Impala,Presto,Drill 诞生了(当然还有无数非著名的交互 SQL 引擎,就不一一列举了)。三个系统的核心理念是,MapReduce 引擎太慢,因为它太通用,太强壮,太保守,我们 SQL 需要更轻量,更激进地获取资源,更专门地对 SQL 做优化,而且不需要那么多容错性保证(因为系统出错了大不了重新启动任务,如果整个处理时间更短的话,比如几分钟之内)。这些系统让用户更快速地处理 SQL 任务,牺牲了通用性稳定性等特性。如果说 MapReduce 是大砍刀,砍啥都不怕,那上面三个就是剔骨刀,灵巧锋利,但是不能搞太大太硬的东西。
这些系统,说实话,一直没有达到人们期望的流行度。因为这时候又两个异类被造出来了。他们是 Hive on Tez / Spark 和 SparkSQL。它们的设计理念是,MapReduce 慢,但是如果我用新一代通用计算引擎 Tez 或者 Spark 来跑 SQL,那我就能跑的更快。而且用户不需要维护两套系统。这就好比如果你厨房小,人又懒,对吃的精细程度要求有限,那你可以买个电饭煲,能蒸能煲能烧,省了好多厨具。
上面的介绍,基本就是一个数据仓库的构架了。底层 HDFS,上面跑 MapReduce/Tez/Spark,再上面跑 Hive,Pig;或者 HDFS 上直接跑 Impala,Drill,Presto,这解决了中低速数据处理的要求。

“”“

------摘自知乎《如何用形象的比喻描述大数据的技术生态?Hadoop、Hive、Spark 之间是什么关系?》,Xiaoyu Ma,对敏感词做了屏蔽处理

Hive

Hive 是一个构建于 Hadoop 顶层的数据仓库工具,支持大规模数据存储、分析,具有良好的可扩展性。某种程度上可以看作是用户编程接口,本身不存储和处理数据。它依赖分布式文件系统 HDFS 存储数据,依赖分布式并行计算模型 MapReduce 处理数据。Hive 定义了简单的类似 SQL 的查询语言——HiveQL,用户可以通过编写的 HiveQL 语句运行 MapReduce 任务,可以很容易把原来构建在关系数据库上的数据仓库应用程序移植到 Hadoop 平台上。

注意,Hive 并不是一个关系数据库。Hive 中没有定义专门的数据格式,由用户指定,需要指定三个属性:列分隔符、行分隔符 、读取文件数据的方法(Hive 中默认有三个文件格式 TextFile,SequenceFile 以及 RCFile)。Hive 在查询数据的时候,由于没有索引,需要扫描整个表,因此延迟较高;另外一个导致 Hive 执行延迟高的因素是 MapReduce 框架,由于 MapReduce 本身具有较高的延迟,因此在利用 MapReduce 执行 Hive 查询时,也会有较高的延迟(相对的,数据库的执行延迟较低,当然,这个低是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候,Hive 的并行计算显然能体现出优势)。
 

Hive 中包含以下数据模型:DB、Table,External Table,Partition,Bucket:


– db:在 hdfs 中表现为 ${hive.metastore.warehouse.dir} 目录下一个文件夹

– table:在 hdfs 中表现所属 db 目录下一个文件夹

– external table:与 table 类似,不过其数据存放位置可以在任意指定路径

– partition:在 hdfs 中表现为 table 目录下的子目录

– bucket:在 hdfs 中表现为同一个表目录下根据 hash 散列之后的多个文件

架构

Hive 的系统架构分为用户接口模块、驱动模块、元数据存储模块。

 

更一般的架构为:

 

用户接口模块

包括 CLI、HWI、JDBC、ODBC、Thrift Server,CLI 即Shell命令行;JDBC/ODBC 是 Hive 的 Java 接口,通过 Thrift Server 接入,然后发送给 Driver;WebGUI 是通过浏览器访问 Hive

驱动模块(Driver)

包括编译器、优化器、执行器等,负责把 HiveQL 语句转换成一系列 MapReduce 作业

元数据存储模块(Metastore)

是一个独立的关系型数据库(自带 derby 数据库,或 MySQL 数据库),由 Cloudera 公司开发的新型查询系统,它提供 SQL 语义,能查询存储在 Hadoop 的 HDFS 和 HBase 上的PB级大数据,在性能上比 Hive 高出3~30倍。元数据包括表的名字、表的列和分区及其属性、表的属性(是否为外部表等)、表的数据所在目录等

工作原理

下图描述了 Hive 和 Hadoop 之间的工作流程:

 

  1. Execute Query
    Hive 接口,如命令行或 Web UI 发送查询驱动程序(任何数据库驱动程序,如 JDBC,ODBC 等)来执行
  2. Get Plan
    在驱动程序帮助下查询编译器,分析查询检查语法和查询计划或查询的要求
  3. Get Metadata
    编译器发送元数据请求到 Metastore(任何数据库)
  4. Send Metadata
    Metastore 发送元数据,以响应编译器
  5. Send Plan
    编译器检查要求,并重新发送计划给驱动程序,到此为止,查询解析和编译完成
  6. Execute Plan
    驱动程序发送执行计划到执行引擎
  7. Execute Job
    在内部,执行作业的过程是一个 MapReduce,执行引擎发送作业给 JobTracker,再进一步分发

    Metadata Ops
    与此同时,在执行时,执行引擎可以通过 Metastore 执行元数据操作
  8. Fetch Result
    执行引擎接收来自数据节点的结果
  9. Send Results
    执行引擎发送这些结果值给驱动程序
  10. Send Results
    驱动程序将结果发送给 Hive 接口

Impala

Impala 是一个运行在 Hadoop 之上的大规模并行处理(MPP)查询引擎,提供对 Hadoop 集群数据的高性能、低延迟的 SQL 查询,使用 HDFS 作为底层存储。它对查询的快速响应使交互式查询和对分析查询的调优成为可能,而这些在针对处理长时间批处理作业的 SQL-on-Hadoop 传统技术上是无法完成的。Impala 与 Hive 元数据存储数据库相结合,在这两个组件之间共享数据库表,并且Impala 与 HiveQL 的语法兼容。因此既可以使用 Impala 也可以使用 Hive 进行建立表、发布查询、装载数据等操作。Impala 可以在已经存在的 Hive 表上执行交互式实时查询。
 

为什么使用 Impala

Impala 缺省使用 Parquet 文件格式,这种列式存储对于典型数据仓库场景下的大查询是最优的(Parquet 是一种列式存储,它不像普通数据仓库那样水平存储数据,而是垂直存储数据;当查询在数值列上应用聚合函数时,这种存储方式将带来巨大的性能提升,原因是只需要读取文件中该列的数据,而不是像 Hive 需要读取整个数据集;Parquet文件格式支持高效的压缩编码方式,例如 Hadoop 和 Hive 缺省使用的 snappy 压缩;Parquet 文件也可用 Hive 和 Pig 处理

适用场景

架构

Impala 由不同的守护进程组成,每种守护进程运行在 Hadoop 集群中的特定主机上,其中 Impalad、Statestored、Catalogd 三个守护进程在其架构中扮演主要角色。

 

Impala守护进程


Impala 的核心组件是一个运行在集群中每个数据节点上的守护进程,物理表现为 Impalad 进程。该进程读写数据文件,接收从 Impala-Shell 命令行、Hue、JDBC、ODBC (Java或其它语言的交互接口)提交的查询请求,将查询工作并行分布到集群的数据节点上,并将查询的中间结果返回给中心协调节点。可以将查询提交至任意一个数据节点上运行的 Impala 守护进程,此守护进程实例担任该查询的协调器,其它节点提交部分中间结果返给协调器,协调器构建查询的最终结果集。当在试验环境使用 Impala-Shell 命令行运行 SQL 时,出于方便性,通常总是连接同一个 Impala 守护进程。而在生产环境负载的集群中,可以采用循环的方式,通过 JDBC 或 ODBC 接口,将每个查询轮流提交至不同的 Impala 守护进程,以达到负载均衡。Impala守护进程持续与 Statestore 进行通信,以确认每个节点健康状况以及是否可以接收新的任务。当集群中的任何 Impala 节点建立、修改、删除任何类型的对象,或者通过 Impala 处理一个 insert 或 load data 语句时,Catalogd 守护进程(Impala 1.2引入)都会发出广播消息。Impala 守护进程会接收这种从 Catalogd 守护进程发出的广播消息。这种后台通信减少了对 refresh 或 invalidate metadata 语句的需要,而在 Impala 1.2版本前,这些语句被用于在节点间协调元数据信息。


Impala Statestore


叫做 Statestore 的 Impala 组件检查集群中所有数据节点上 Impala 守护进程的健康状况,并将这些信息持续转发给每个 Impala 守护进程,其物理表现为一个名为 Statestored 的守护进程,该进程只需要在集群中的一台主机上启动。如果 Impala 守护进程由于硬件、软件、网络或其它原因失效,Statestore 会通知所有其它的 Impala 守护进程,这样以后的查询就不会再向不可到达的节点发出请求。 Statestore 的目的只是在发生某种错误时提供帮助,因此在正常操作一个 Impala 集群时,它并不是一个关键组件。即使 Statestore 没有运行或者不可用,Impala 守护进程依然会运行,并像通常一样在它们中分法任务。 这时如果一个 Impala 守护进程失效,仅仅是降低了集群的鲁棒性。当 Statestore 恢复可用后,它会重建与 Impala 守护进程之间的通信并恢复监控功能。在 Impala 中,所有负载均衡和高可用的考虑都是用于 Impala 守护进程的。Statestored 和 Catalogd 进程没有高可用的需求,因为这些进程即使出现问题也不会引起数据丢失。当这些进程由于所在的主机停机而变成不可用时,可以这样处理:先停止 Impala 服务,然后删除 Impala StateStore 和 Impala Catalog 服务器角色,再在另一台主机上添加这两个角色,最后重启 Impala 服务。


Impala Catalog 服务


称为 Catalog 服务的 Impala 组件将 Impala SQL 语句产生的元数据改变转发至集群中的所有数据节点,其物理表现为一个名为 Catalogd 的守护进程,该进程只需要在集群中的一台主机上启动,而且应该与 Statestored 进程在同一台主机上。由于 Catalog 服务的存在,当通过执行 Impala 语句而改变元数据时,不需要再发出 refresh 或 invalidate metadata 语句。然而,当通过 Hive 执行建立表、装载数据等操作后,在一个 Impala 节点上执行查询前,仍然需要先发出 refresh 或 invalidate metadata 语句。例如,通过 Impala 执行的 create table、insert 或其它改变表或改变数据的操作,无需执行 refresh and invalidate metadata 语句。而如果这些操作是用过 Hive 执行的,或者是直接操纵的 HDFS 数据文件,仍需执行 refresh and invalidate metadata 语句(只需在一个 Impala 节点执行,而不是全部节点)。缺省情况下,元数据在 Impala 启动时异步装载并缓存,这样 Impala 可以立即接收查询请求。如果想让 Impala 等所有元数据装载后再接收查询请求,需要设置 Catalogd 的配置选项 load_catalog_in_background=false

Impala的元数据和元数据存储


前面讨论 Impala 如何与 Hive一起使用时提到,Impala 使用一个叫做 Metastore 的数据库维护它的表定义信息。同时 Impala 还跟踪其它数据文件底层特性的元数据,如 HDFS 中数据块的物理位置信息。对于一个有很多分区或很多数据的大表,获取它的元数据可能很耗时,有时需要花上几分钟的时间。因此每个 Impala 节点都会缓存这些元数据,当后面再查询该表时,就可以复用缓存中的元数据。如果表定义或表中的数据更新了,集群中所有其它的 Impala 守护进程在查询该表前, 都必须能收到最新的元数据,并更新自己缓存的元数据。在 Impala 1.2或更高版本中,这种元数据的更新是自动的,由 Catalogd 守护进程为所有通过 Impala 发出的 DDL 和 DML 语句进行协调。对于通过 Hive 发出的 DDL 和 DML,或者手工改变了 HDFS 文件的情况,还是需要在 Impala 中使用 refresh 语句(当新的数据文件被加到已有的表上)或 invalidate metadata 语句(新建表、删除表、执行了 HDFS 的 rebalance 操作,或者删除了数据文件)。Invalidate metadata 语句获取 Metastore 中存储的所有表的元数据。如果能够确定在 Impala 外部只有特定的表被改变,可以为每一个受影响的表使用 refresh 表名,该语句只获取特定表的最新元数据。

Spark

Apache Spark 是一个围绕速度、易用性和复杂分析构建的大数据处理框架,最初在2009年由加州大学伯克利分校的 AMPLab 开发,并于2010年成为 Apache 的开源项目之一,与 Hadoop 和 Storm 等其他大数据和 MapReduce 技术相比,Spark 有如下优势:

适用场景

架构

Hadoop 存在缺陷:基于磁盘,无论是 MapReduce 还是 YARN 都是将数据从磁盘中加载出来,经过 DAG,然后重新写回到磁盘中,计算过程的中间数据又需要写入到 HDFS 的临时文件,这些都使得 Hadoop 在大数据运算上表现太“慢”,因此 Spark 应运而生。通常当需要处理的数据量超过了单机尺度(比如我们的计算机有4GB的内存,而我们需要处理100GB以上的数据),这时我们可以选择Spark 集群进行计算;有时我们可能需要处理的数据量并不大,但是计算很复杂,需要大量的时间,这时我们也可以选择利用 Spark 集群强大的计算资源,并行化地计算,其架构示意图如下:

 

Spark Core:包含 Spark 的基本功能,尤其是定义 RDD 的 API、操作以及在这两者上的动作;其他 Spark 的库都是构建在 RDD 和 Spark Core 之上的

Spark SQL:提供通过 Apache Hive 的 SQL 变体 Hive 查询语言(HiveQL)与 Spark 进行交互的API,每个数据库表被当做一个 RDD,Spark SQL 查询被转换为 Spark 操作;Spark 提供的 SQL 形式的对接 Hive、JDBC、HBase 等各种数据渠道的 API,用 Java 开发人员的思想来讲就是面向接口、解耦合,ORMapping、Spring Cloud Stream 等类似的思想 

Spark Streaming:基于 SparkCore 实现的可扩展、高吞吐、高可靠性的实时数据流处理,支持从 Kafka、Flume 等数据源处理后存储到 HDFS、DataBase、Dashboard 中,对实时数据流进行处理和控制;Spark Streaming 允许程序能够像普通 RDD 一样处理实时数据

MLlib:一个常用机器学习算法库,算法被实现为对 RDD 的Spark操作,这个库包含可扩展的学习算法,比如分类、回归等需要对大量数据集进行迭代的操作。

GraphX:控制图、并行图操作和计算的一组算法和工具的集合,GraphX 扩展了 RDD API,包含控制图、创建子图、访问路径上所有顶点的操作
 

工作原理

 

Cluster Manager 在 Standalone 模式中即为 Master 主节点,控制整个集群,监控 Worker;在 YARN 模式中为资源管理器负责分配资源,有点像 YARN 中 ResourceManager 那个角色,大管家握有所有的干活的资源,属于乙方的总包
WorkerNode 是可以干活的节点,听大管家 ClusterManager 差遣,是真正有资源干活的主,负责控制计算节点,启动 Executor 或者 Driver
Executor 是在 WorkerNode 上起的一个进程,相当于一个包工头,负责准备 Task 环境和执行
Task 负责内存和磁盘的使用,是施工项目里的每一个具体的任务
Driver 是统管 Task 的产生与发送给 Executor 的,运行 Application 的 main() 函数,是甲方的司令员
SparkContext 是与 ClusterManager 打交道的,负责给钱申请资源的,是甲方的接口人

整个互动流程是这样的:

  1. 甲方来了个项目,创建了 SparkContext,SparkContext 去找 ClusterManager(可以是Standalone,Mesos,Yarn)申请 Executor 资源同时给出报价,需要多少 CPU 和内存等资源,并启动 StandaloneExecutorbackend
  2. ClusterManager 去找 WorkerNode 并启动 Excutor,并介绍 Excutor 给 Driver 认识
  3. Driver 根据施工图拆分一批批的 Task,将 Task 送给 Executor 去执行(SparkContext 构建成 DAG 图,将 DAG 图分解成 Stage、将 Taskset 发送给 Task Scheduler,最后由 Task Scheduler 将 Task 发送给 Executor 运行)
  4. Executor 接收到 Task 后准备 Task 运行时依赖并执行,并将执行结果返回给 Driver
  5. Driver 会根据返回回来的 Task 状态不断的指挥下一步工作,直到所有 Task 执行结束,运行完释放所有资源

特点:多线程运行、运行过程与资源管理器无关、Task 采用了数据本地性和推测执行来优化

附:RDD 的依赖关--窄依赖和宽依赖

窄依赖(narrow dependency):是指每个父 RDD 的一个 Partition 最多被子 RDD 的一个 Partition 所使用,例如 map、filter、union 等操作都会产生窄依赖;(独生子女)即 rdd 中的每个 partition 仅仅对应父 rdd 中的一个 partition;父 rdd 里面的 partition 只去向子 rdd 里的某一个 partition,这叫窄依赖;如果父 rdd 里面的某个 partition 会去子 rdd 里面的多个 partition,那它就一定是宽依赖 
宽依赖(shuffle dependency):是指一个父 RDD 的 Partition 会被多个子 RDD 的 Partition 所使用,例如 groupByKey、reduceByKey、sortByKey 等操作都会产生宽依赖;(超生)每一个父 rdd 的 partition 数据都有可能传输一部分数据到子 rdd 的每一个 partition 中,即子 rdd 的多个 partition 依赖于父 rdd;宽依赖划分成一个 Stage

对比

由于 Spark 是一种计算框架,因此后续的对比侧重于用 SparkSQL 进行对比

Hive 与 Impala

相同点

不同点

Hive 与 SparkSQL

相同点

不同点

SparkSQL 与 Impala

相同点

不同点

标签:HDFS,Impala,Hadoop,Hive,查询,Spark,数据
来源: https://blog.csdn.net/weixin_41559709/article/details/118934929