个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala

有了 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,对敏感词做了屏蔽处理

1、Hive

Hive 是一个构建于 Hadoop 顶层的数据仓库工具(注意区别分布式计算框架 MapReduce、Storm、Spark,不同的引擎在SQL翻译的逻辑和底层的程序是不一样的,比如 MR 引擎会把 SQL 翻译成 MR 、Spark 引擎会把 SQL 翻译成 RDD 程序、Tez 引擎可以理解为在 MR 的基础上做了 DAG 方向的基于内存的 shuffle 优化),支持大规模数据存储、分析,具有良好的可扩展性。某种程度上可以看作是用户编程接口,本身不存储和处理数据。它依赖分布式文件系统 HDFS 存储数据,依赖分布式并行计算模型 MapReduce 处理数据(底层计算的引擎默认是 MapReduce,可以将引擎更换为 Spark/Tez)。Hive 定义了简单的类似 SQL 的查询语言——HiveQL,用户可以通过编写的 HiveQL 语句运行 MapReduce 任务,可以很容易把原来构建在关系数据库上的数据仓库应用程序移植到 Hadoop 平台上。

Hive 是通过构建元数据,映射 HDFS 文件构建成表,本质还是 HDFS,实现离线大数据仓库。注意,Hive 并不是一个关系数据库。

Hive 中没有定义专门的数据格式,由用户指定,需要指定三个属性:列分隔符、行分隔符 、读取文件数据的方法(Hive 中默认有三个文件格式 TextFile,SequenceFile 以及 RCFile)。

Hive 在查询数据的时候,由于没有索引,需要扫描整个表,因此延迟较高;另外一个导致 Hive 执行延迟高的因素是 MapReduce 框架,由于 MapReduce 本身具有较高的延迟,因此在利用 MapReduce 执行 Hive 查询时,也会有较高的延迟(相对的,数据库如 MySQL 的执行延迟较低,当然,这个低是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候,Hive 的并行计算显然能体现出优势)。
个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala_第1张图片

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

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

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

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

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

1.1 优点

  • 操作类SQL语法,简单容易上手,提升快速开发能力
  • 免去写 MapReduce,减少开发人员的开发时间成本
  • 优势在于处理大数据、实时性要求低的任务
  • 可以与 Impala/Spark 等共享元数据
  • 易于扩展,支持自定义函数,自定义存储位置等

1.2 缺点

  • HiveQL 表达能力有限
    1. 迭代式算法无法表达(复杂的逻辑算法不好封装)
  • Hive 的效率比较低
    1. 数据挖掘方面不擅长,由于 MapReduce 数据处理流程的限制(比较慢,因为底层的缺点也都还在),效率更高的算法无法实现
    2. Hive 自动生成的 MapReduce 作业,通常情况下不够智能化(机器翻译比较死板,可能不是最优解,但是一定可以实现)
    3. Hive 调优比较困难,粒度较粗(只能在框架的基础上优化,不能深入底层 MR 程序优化)

1.3 架构

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

个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala_第2张图片
更一般的架构为:
个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala_第3张图片
个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala_第4张图片

从架构图上可以很清楚地看出 Hive 和 Hadoop(MapReduce,HDFS)的关系:

  • Hive是最上层,即客户端层或者作业提交层(包含 Driver)
  • MapReduce/Yarn 是中间层,也就是计算层
  • HDFS 是底层,也就是存储层

1.3.1 用户接口模块

包括 CLI、HWI、JDBC、ODBC、Thrift Server;CLI 即 Shell 命令行;Thtift Server 是 Facebook 提供的一种软件框架,可以用来进行可扩展跨语言服务的框架,Hive 集成了该服务,能让不用的语言调用该服务;JDBC/ODBC 是 Hive 的 Java 接口,通过 Thrift Server 接入,然后发送给 Driver;WebGUI 是通过浏览器访问 Hive

1.3.2 驱动模块(Driver)

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

1.3.3 元数据存储模块(Metastore)

是一个独立的关系型数据库(自带 derby 数据库,或 MySQL 数据库),由 Cloudera 公司开发的新型查询系统,它提供 SQL 语义,能查询存储在 Hadoop 的 HDFS 和 HBase 上的 PB 级大数据,在性能上比 Hive 高出3~30倍。元数据包括表的名字、表的列和分区及其属性、表的属性(是否为外部表等)、表的数据所在目录等; Metastore 默认存在自带的 derby 数据库中,缺点就是不适合多用户操作,并且数据存储目录不固定,数据库跟着Hive走,极度不方便管理,解决方案就是存在我们自己创建的 MySQL 库(本地或远程,远程模式的特点是:Hive 服务和 MetaStore 在不同的进程内,可能是不同的机器,“远”指的是 MetaStore 和 Hive 服务离得“远”)

1.4 工作原理

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

个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala_第5张图片

  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 接口

1.4.1 Hive,MySql 和 HDFS 之间的关系

个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala_第6张图片

  • Hive 不存储数据,Hive 需要分析计算的数据,以及计算结果后的数据实际存储在分布式系统上,如 HDFS 上
  • Hive 某种程度来说也不进行数据计算,只是个解释器,只是将用户需要对数据处理的逻辑,通过 SQL 编程提交后解释成 MapReduce 程序,然后将这个 MR 程序提交给 Yarn 进行调度执行,所以实际进行分布式运算的是 MapReduce 程序
  • Hive 为了能操作 HDFS 上的数据集,需要知道数据的切分格式,如行列分隔符,存储类型,是否压缩,数据的存储地址等信息,为了方便以后操作需要将这些信息通过一张表存储起来,然后将这张表(元数据)存储到 MySQL 中;存储到 MySQL 里是因为 Hive 本身就是一个解释器,所以他不存储数据

1.4.2 MapReduce 实现原理

可以通过 Explain 查看一个 SQL 如何变成 MapReduce 作业的过程,例如在 Hive Cli 中执行:explain sql语句 就能看到,例子如下:
个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala_第7张图片个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala_第8张图片个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala_第9张图片

Hive 把复杂 SQL 分解成多个 MapReduce Chain 执行,各 MR 的中间结果存为 HDFS 的临时文件,然后链式跑完即可获得最终结果。因此,只需明白其核心即可见微知著,下面介绍 join、group by 和 distinct 的原理(摘抄自美团技术团队的总结)

Join
select u.name, o.orderid from order o join user u on o.uid = u.uid;

在 Map 的输出 Value 中为不同表的数据打上 Tag 标记,在 Reduce 阶段根据 Tag 判断数据来源。MapReduce的过程如下(这里只是说明最基本的 Join 的实现,还有其他的实现方式):

个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala_第10张图片

Group By

select rank, isonline, count(*) from city group by rank, isonline;

将 GroupBy 的字段组合为 Map 的输出 Key 值,利用 MapReduce 的排序,在 Reduce 阶段保存 LastKey 区分不同的 Key。MapReduce 的过程如下(当然这里只是说明 Reduce 端的非 Hash 聚合过程):

个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala_第11张图片

Distinct
select dealid, count(distinct uid) num from order group by dealid;

当只有一个 Distinct 字段时,如果不考虑 Map 阶段的 Hash GroupBy,只需要将 GroupBy 字段和 Distinct 字段组合为 Map 输出 key,利用 MapReduce 的排序,同时将 GroupBy 字段作为 Reduce 的 Key,在 Reduce 阶段保存 LastKey 即可完成去重:

个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala_第12张图片

1.5 文件格式

(1) Textfile

文本格式,Hive 的默认格式,数据不压缩,磁盘开销大、数据解析开销大。行式存储

对应的 hive API 为:org.apache.hadoop.mapred.TextInputFormat 和 org.apache.hive.ql.io.HiveIgnoreKeyTextOutputFormat

(2)SequenceFile

Hadoop 提供的一种二进制文件格式,是 Hadoop 支持的标准文件格式(其他生态系统并不适用),可以直接将对序列化到文件中,所以 sequencefile 文件不能直接查看,可以通过 Hadoop fs -text 查看。具有使用方便,可分割,可压缩,可进行切片。行式存储

对应 hive API 为:org.apache.hadoop.mapred.SequenceFileInputFormat 和 org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat

(3)RCFile

是一种行列存储相结合的存储方式,先将数据按行进行分块再按列式存储,保证同一条记录在一个块上,避免读取多个块,有利于数据压缩和快速进行列存储。列式存储

对应的 hive API 为:org.apache.hadoop.hive.ql.io.RCFileInputFormat 和 org.apache.hadoop.hive.ql.io.RCFileOutputFormat

(4)ORCFile

orcfile 是对 rcfile 的优化,可以提高 hive 的读写、数据处理性能,提供更高的压缩效率(目前主流选择之一)。列式存储

(5)Parquet

一种列格式,可提供对其他 hadoop 工具的可移植性, 包括 Hive, Drill, Impala, Crunch, and Pig

对应的 hive API 为:org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat 和 org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat

(6)Avro

Avro 是一个数据序列化系统,设计用于支持大批量数据交换的应用。它的主要特点有:支持二进制序列化方式,可以便捷,快速地处理大量数据;动态语言友好,Avro 提供的机制使动态语言可以方便地处理 Avro 数据

对应的 hive API 为:org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat 和 org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat

几种文件存储格式的性能测试结果:

存储格式 ORC Sequencefile Parquet RCfile Avro
数据压缩后大小 1.8G 67.0G 11G 63.8G 66.7G
存储耗费时间 535.7s 625.8s 537.3s 543.48 544.3
SQL查询响应速度 19.63s 184.07s 24.22s 88.5s 281.65s

1.6 数据倾斜

定义: 由于数据分布不均匀,造成数据热点。

现象: 一个或几个 key 的记录数与平均记录数差异过大,最长时长远大于平均时长。任务进度长时间维持在99%(或100%),查看任务监控页面,发现只有少量(1个或几个)reduce 子任务未完成。

数据倾斜优化:一般分为 join 引起和 group by 引起分别解决。

操作 原因 现象
Group by 分组 key 集中 处理某 key 值的 reduce 非常耗时
Join 关联 key 集中(例如关联字段空值过多) 处理某 key 值的 reduce 非常耗时

1.6.1 Group by 引起的数据倾斜

分两方面优化:

第一个:
set hive.map.aggr=true;

set hive.groupby.mapaggr.checkinterval=100000;

set hive.map.aggr.hash.min.reduction=0.5;

hive.map.aggr=true(默认)参数控制在 group by 的时候是否 map 局部聚合,但也不是都会局部聚合,如果聚合前后差别不是很大,聚合也就没什么意义了。

后两个设置是判断是否需要做 map 局部聚合,即:预先取100000条数据聚合,如果聚合后的条数/100000>0.5,则不再聚合。

第二个:

set Hive.groupby.skewindata=true;

控制启动两个 MR Job 完成,第一个 Job 先不按 GroupBy 字段分发,而是随机分发做一次聚合,然后启动第二个 Job,拿前面聚合过的数据按 GroupBy 字段分发计算出最终结果。但是否生效还存在限制,详情见 Hive-hive.groupby.skewindata 配置相关问题调研

1.6.2 Join 引起的数据倾斜

优化主要分两个方向:skew join 和 重写业务逻辑

Skew join:

set hive.optimize.skewjoin=true;

set hive.skewjoin.key=100000;

记录超过 hive.skewjoin.key(默认100000)阈值的 key 值先写入 hdfs,然后再进行一个 map join 的 job 任务,最终和其他 key 值的结果合并为最终结果。其过程如下图:

个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala_第13张图片

重写业务逻辑

这个需要结合具体的场景重写,例如:在日志表与用户表关联时候(通过 user_id 关联),直接关联可能导致 user_id 为 null 的发生数据倾斜,此时可以把日志表中 user_id 为 null 的单独处理,如下:

SELECT a.xx, b.yy 
FROM log a 
JOIN users b 
ON a.user_id IS NOT NULL AND a.user_id = b.user_id 
UNION ALL 
SELECT a.xx, NULL AS yy 
FROM log a 
WHERE a.user_id IS NULL;

1.7 常见问题

请说明 hive 中 Sort By,Order By,Cluster By,Distrbute By 各代表什么意思

order by:会对输入做全局排序,因此只有一个 reducer(多个 reducer 无法保证全局有序)。只有一个 reducer,会导致当输入规模较大时,需要较长的计算时间

sort by:对分区内的数据进行排序,不是全局排序,其在数据进入 reducer 前完成排序

distribute by:对 map 输出进行分区,按照指定的字段对数据进行划分输出到不同的 reducer 中。常和 sort by 一起使用,例如:select mid, money, name from store distribute by mid sort by mid asc, money asc

cluster by:当 distribute by 和 sort by 字段相同时,可使用 cluster by 方式替代,cluster by 具有 distribute by 和 sort by 的组合功能。但是排序只能是升序排序,不能指定排序规则为 ASC 或者 DESC

NULL 在 hive 的一般处理

NULL 默认的存储都是 \N,可以在建表时通过 serialization.null.format 设置

NULL 值的过滤,一般是 is null 和 is not null

multi-group 新特性的好处

multi group by 可以将查询中的多个 group by 操作组装到一个 MapReduce 任务中,起到优化作用

2、 Impala

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

2.1 起源

Impala 最开始是参照 Dremel 系统进行设计的。Dremel 是 Google 的交互式数据分析系统,它构建于 Google 的 GFS(Google File System)等系统之上,支撑了 Google 的数据分析服务 BigQuery 等诸多服务。

Dremel 的技术亮点主要有两个:一是实现了嵌套型数据的列存储;二是使用了多层查询树,使得任务可以在数千个节点上并行执行和聚合结果。

列存储在关系型数据库中并不陌生,它可以减少查询时处理的数据量,有效提升查询效率。Dremel 的列存储的不同之处在于它针对的并不是传统的关系数据,而是嵌套结构的数据。Dremel 可以将一条条的嵌套结构的记录转换成列存储形式,查询时根据查询条件读取需要的列,然后进行条件过滤,输出时再将列组装成嵌套结构的记录输出,记录的正向和反向转换都通过高效的状态机实现。

另外,Dremel 的多层查询树则借鉴了分布式搜索引擎的设计,查询树的根节点负责接收查询,并将查询分发到下一层节点,底层节点负责具体的数据读取和查询执行,然后将结果返回上层节点。

Impala 在受到 Google 的 Dremel 启发下开发的实时交互 SQL 大数据查询工具,Impala 没有再使用缓慢的 Hive+MapReduce 批处理,而是通过使用与商用并行关系数据库中类似的分布式查询引擎(由 Query Planner、Query Coordinator 和 Query Exec Engine 三部分组成),可以直接从 HDFS 或 HBase 中用 SELECT、JOIN 和统计函数查询数据,从而大大降低了延迟。

因此可以说,Impala 其实就是 Hadoop 的 Dremel。

2.2 为什么使用 Impala

  • Impala 和 Kudu 高度耦合(都是 Cloudera亲生的),共同提供实时性
  • 基于内存进行计算,能够对 PB 级数据进行交互式实时查询和分析
  • Impala 可以使用 SQL 访问存储在 Hadoop 上的数据,而传统的 MapReduce 则需要掌握 Java 技术
  • Impala 提供 SQL 直接访问 HDFS 文件系统、HBase 数据库系统或 Amazon S3 的数据
  • Impala 在 Hadoop 生态系统之上提供并行处理数据库技术,允许用户执行低延迟的交互式查询
  • Impala 大都能在几秒或几分钟内返回查询结果,而相同的 Hive 查询通常需要几十分钟甚至几小时完成
  • Impala 的实时查询引擎非常适合对 Hadoop 文件系统上的数据进行分析式查询
  • 由于 Impala 能实时给出查询结果,它能够很好地与 Pentaho、Tableau 这类报表或可视化工具一起使用(这些工具已经配备了 Impala 连接器,可以从 GUI 直接执行可视化查询)
  • Impala 与 Hadoop 生态圈相结合,内置对所有 Hadoop 文件格式(ORC、Parquet等等)的支持,这意味着可以使用 Hadoop 上的各种解决方案存储、共享和访问数据,同时避免了数据竖井,并且降低了数据迁移的成本

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

2.3 劣势

  • 对内存依赖性大
  • 依赖于 Hive 的 MetaStore(Impala 的元数据存储在 Hive 的 MetaStore 中,故欲使用 Impala,应保证 Hive 安装成功)
  • 实践过程中,分区超过1w,性能严重下降
  • 稳定性不如 Hive
  • 每当新的记录/文被添加到 HDFS 中的数据目录时,该表需要被刷新

2.4 适用场景

  • 需要低延迟得到查询结果
  • 快速分析型查询
  • 实时查询
  • 需要多次处理相同类型的查询

2.5 架构

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

个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala_第14张图片

2.5.1 Impala 守护进程**(Impala Daemon)**

Impala 的核心组件是一个运行在集群中每个数据节点上的守护进程,物理表现为 Impalad 进程,由三个模块组成:Query Planner、Query Coordinator 和 Query Executor,前两个模块组成前端,负责接收 SQL 查询请求,解析 SQL 并转换成执⾏计划,交由后端执⾏。

该进程读写数据文件,接收从 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 版本前,这些语句被用于在节点间协调元数据信息。

2.5.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 服务。

2.5.3 Impala Catalog 服务

称为 Catalog 服务的 Impala 组件将 Impala SQL 语句产生的元数据改变转发至集群中的所有数据节点,其物理表现为一个名为 Catalogd 的守护进程,该进程只需要在集群中的一台主机上启动,而且应该与 Statestored 进程在同一台主机上(因为 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

2.5.4 Impala 的元数据和元数据存储

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 表名,该语句只获取特定表的最新元数据。

2.6 工作原理

个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala_第15张图片

1.Client 提交任务
Client 发送⼀个 SQL 查询请求到任意⼀个 Impalad 节点,会返回⼀个 queryId ⽤于之后的客户端操作
2.生成查询计划(单机计划、分布式执行计划)
SQL 提交到 Impalad 节点之后,Analyser 依次执⾏ SQL 的词法分析、语法分析、语义分析等操作;从 MySQL 元数据库中获取元数据,从 HDFS 的 NameNodes 中获取数据地址,以得到存储这个查询相关数据的所有数据节点。

生成查询计划分为两个阶段:(1)生成单机查询计划,单机执行计划与关系数据库执行计划相同,所用查询优化方法也类似(2)生成分布式查询计划。 根据单机执行计划, 生成真正可执行的分布式执行计划,降低数据移动, 尽量把数据和计算放在一起;注意,单机查询计划不能直接执行, 必须转换成分布式查询计划。

  • 单机执行计划:根据上⼀步对 SQL 语句的分析,由 Planner 先⽣成单机的执⾏计划,该执⾏计划是有 PlanNode 组成的⼀棵树,这个过程中也会执⾏⼀些 SQL 化,例如 Join 顺序改变、谓词下推等。
  • 分布式并⾏物理计划:将单机执⾏计划转换成分布式并⾏物理执⾏计划,物理执⾏计划由⼀个个的 Fragment 组成,Fragment 之间有数据依赖关系,处理过程中要在原有的执⾏计划之上加⼊⼀些 ExchangeNode 和 DataStreamSink 信息等
    • Fragment :SQL ⽣成的分布式执⾏计划的⼀个⼦任务
    • DataStreamSink:传输当前的 Fragment 输出数据到不同的节点

3.任务调度和分发
Coordinator 将 Fragment(⼦任务)根据数据分区信息发配到不同的 Impalad 节点上执⾏。Impalad 节点接收到执⾏ Fragment 请求交由 Executor 执⾏
4.Fragment 之间的数据依赖
每⼀个 Fragment 的执⾏输出通过 DataStreamSink 发送到下⼀个 Fragment,Fragment 运⾏过程中不断向 Coordinator 节点汇报当前运⾏状态
5. 结果汇总
查询的 SQL 通常情况下需要有⼀个单独的 Fragment ⽤于结果的汇总,它只在 Coordinator 节点运⾏,将多个节点的最终执⾏结果汇总,转换成 ResultSet 信息
6. 获取结果
客户端调⽤获取 ResultSet 的接⼝,读取查询结果。

2.6.1 单机执行计划

以⼀个SQL例⼦来展示查询计划:

select
t1.n1,
t2.n2,
count(1) as c
from t1 join t2 on t1.id = t2.id
join t3 on t1.id = t3.id
where t3.n3 between ‘a’ and ‘f’
group by t1.n1, t2.n2
order by c desc
limit 100;

个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala_第16张图片

  • 第一步去扫描 t1 表中的需要的数据 n1、id 列,再扫描 t2 表需要的数据 n2、id 列,然后这部分数据进行 Join 操作。
  • t1 表和 t2 表关联后,同样的操作,将中间结果表和 t3 进行关联 Join,此处 Impala 会使用谓词下推优化,只读取需要的数据进行表 Join。
  • 将最后的结果数据进行聚合操作。

2.6.2 分布式执行计划

个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala_第17张图片

分布式执⾏计划中涉及到多表的 Join,Impala 会根据表的⼤⼩来决定 Join 的⽅式,主要有两种分别是 Hash Join 与 Broadcast Join

上⾯分布式执⾏计划中可以看出 T1、T2 表⼤⼀些,⽽ T3 表⼩⼀些,所以对于 T1 与 T2 的 Join,Impala选择使⽤ Hash Join,对于 T3 表选择使⽤ Broadcast ⽅式,直接把 T3 表⼴播到需要 Join 的节点上:

  1. T1 和 T2 使⽤ Hash join,此时需要按照 id 的值分别将 T1 和 T2 分散到不同的 Impalad 进程,但是相同的 id 会散列到相同的 Impalad 进程,这样每⼀个 Join之 后是全部数据的⼀部分。
  2. T1 与 T2 Join 之后的结果数据再与 T3 表进⾏ Join,此时 T3 表采⽤ Broadcast ⽅式把⾃⼰全部数据(id 列)⼴播到需要的 Impala 节点上。
  3. T1、T2、T3 Join 之后再根据 Group by 执⾏本地的预聚合,每⼀个节点的预聚合结果只是最终结果的⼀部分(不同的节点可能存在相同的 group by 的值),需要再进⾏⼀次全局的聚合。
  4. 全局的聚合同样需要并⾏,则根据聚合列进⾏ Hash 分散到不同的节点执⾏ Merge 运算(其实仍然是⼀次聚合运算),⼀般情况下为了较少数据的⽹络传输, Impala 会选择之前本地聚合节点做全局聚合⼯作。
  5. 通过全局聚合之后,相同的 key 只存在于⼀个节点,然后对于每⼀个节点进⾏排序和 TopN 计算,最终将每⼀个全局聚合节点的结果返回给 Coordinator 进⾏合并、排序、limit 计算,返回结果给⽤户。

2.7 与 Hive 的关系

2.7.1 相对于 Hive 使用的优化技术

  • 没有使用 MapReduce 进行并行计算,虽然 MapReduce 是非常好的并行计算框架,但它更多的面向批处理模式,而不是面向交互式的 SQL 执行;与 MapReduce 相比:Impala 把整个查询分成一执行计划树,而不是一连串的 MapReduce 任务,在分发执行计划后,Impala使用拉式获取数据的方式获取结果,把结果数据组成按执行树流式传递汇集,减少了把中间结果写入磁盘的步骤,再从磁盘读取数据的开销;Impala 使用服务的方式避免每次执行查询都需要启动的开销,即相比 Hive 没了 MapReduce 启动时间。
  • 使用 LLVM 产生运行代码,针对特定查询生成特定代码,同时使用 Inline 的方式减少函数调用的开销,加快执行效率。
  • 充分利用可用的硬件指令
  • 更好的 IO 调度,Impala 知道数据块所在的磁盘位置能够更好的利用多磁盘的优势,同时 Impala 支持直接数据块读取和本地代码计算 checksum。
  • 通过选择合适的数据存储格式可以得到最好的性能(Impala 支持多种存储格式)。
  • 最大使用内存,中间结果不写磁盘,及时通过网络以 stream 的方式传递。

2.7.2 对比

相同点
  • 数据存储:使用相同的存储数据池都支持把数据存储于 HDFS,HBase。
  • 元数据:两者使用相同的元数据。
  • SQL 解释处理:比较相似都是通过词法分析生成执行计划。
不同点
  • 执行计划:
    • Hive:依赖于 MapReduce 执行框架,执行计划分成 map->shuffle->reduce->map->shuffle→reduce…的模型。如果一个 Query 会被编译成多轮 MapReduce,则会有更多的写中间结果。由于 MapReduce 执行框架本身的特点,过多的中间过程会增加整个 Query 的执行时间。
    • Impala:把执行计划表现为一棵完整的执行计划树,可以更自然地分发执行计划到各个 Impalad 执行查询,而不用像 Hive 那样把它组合成管道型的 map→reduce 模式,以此保证 Impala 有更好的并发性和避免不必要的中间 sort 与 shuffle。
  • 数据流:
    • Hive:采用推的方式,每一个计算节点计算完成后将数据主动推给后续节点。
    • Impala:采用拉的方式,后续节点通过 getNext 主动向前面节点要数据,以此方式数据可以流式的返回给客户端,且只要有1条数据被处理完,就可以立即展现出来,而不用等到全部处理完成,更符合 SQL 交互式查询使用。
  • 内存使用:
    • Hive:在执行过程中如果内存放不下所有数据,则会使用外存,以保证 Query 能顺序执行完。每一轮 MapReduce 结束,中间结果也会写入 HDFS 中,同样由于 MapReduce 执行架构的特性,shuffle 过程也会有写本地磁盘的操作。
    • Impala:在遇到内存放不下数据时,当前版本1是直接返回错误,而不会利用外存,以后版本应该会进行改进。这使得 Impala 目前处理 Query 会受到一定的限制,最好还是与 Hive 配合使用。Impala 在多个阶段之间利用网络传输数据,在执行过程不会有写磁盘的操作(insert 除外)。
  • 调度:
    • Hive:任务调度依赖于 Hadoop 的调度策略。
    • Impala:调度由自己完成,目前只有一种调度器 simple-schedule,它会尽量满足数据的局部性,扫描数据的进程尽量靠近数据本身所在的物理机器。调度器目前还比较简单,在 SimpleScheduler::GetBackend 中可以看到,现在还没有考虑负载,网络 IO 状况等因素进行调度。但目前 Impala 已经有对执行过程的性能统计分析,应该以后版本会利用这些统计信息进行调度吧。
  • 容错:
    • Hive:依赖于 Hadoop 的容错能力。
    • Impala:在查询过程中,没有容错逻辑,如果在执行过程中发生故障,则直接返回错误(这与 Impala 的设计有关,因为 Impala 定位于实时查询,一次查询失败,再查一次就好了,再查一次的成本很低)。但从整体来看,Impala 是能很好的容错,所有的 Impalad 是对等的结构,用户可以向任何一个 Impalad 提交查询,如果一个 Impalad 失效,其上正在运行的所有 Query 都将失败,但用户可以重新提交查询由其它 Impalad 代替执行,不会影响服务。对于 State Store 目前只有一个,但当 State Store 失效,也不会影响服务,每个 Impalad 都缓存了 State Store 的信息,只是不能再更新集群状态,有可能会把执行任务分配给已经失效的 Impalad 执行,导致本次 Query 失败。
  • 适用面:
    • Hive:复杂的批处理查询任务,数据转换任务。
    • Impala:实时数据分析,因为不支持 UDF,能处理的问题域有一定的限制,与 Hive 配合使用,对 Hive 的结果数据集进行实时分析。

Via 煜哥:

Impala(常和 Kudu 搭配使用)能实现 transaction 数据摄入实时性、响应实时查询的完整性

Hive 没有 transaction,因此加入 partition,比如 by hour,那么就可以按小时实时更新

Hive 主要公司内部用,不追求实时响应速度

稳健性 Hive on MapReduce > Spark > Impala,因为 Hive 每一步 MapReduce 都有一个入盘的操作,Impala 是 MPP,所以没有

速度 Impala > Spark > Hive

因为 Impala 基于 MPP,默认使用所有资源,省了很多资源分配的操作,但会存在一个人查询要1s,100个人分别同时查询要100s ,同时如果一个地方出错,由于是基于 MPP,所以不能”断点续传“

  • Hive:复杂的批处理查询任务,数据转换任务。
  • Impala:实时数据分析,因为不支持 UDF,能处理的问题域有一定的限制,与 Hive 配合使用,对 Hive 的结果数据集进行实时分析。

Via 煜哥:

Impala(常和 Kudu 搭配使用)能实现 transaction 数据摄入实时性、响应实时查询的完整性

Hive 没有 transaction,因此加入 partition,比如 by hour,那么就可以按小时实时更新

Hive 主要公司内部用,不追求实时响应速度

稳健性 Hive on MapReduce > Spark > Impala,因为 Hive 每一步 MapReduce 都有一个入盘的操作,Impala 是 MPP,所以没有

速度 Impala > Spark > Hive

因为 Impala 基于 MPP,默认使用所有资源,省了很多资源分配的操作,但会存在一个人查询要1s,100个人分别同时查询要100s ,同时如果一个地方出错,由于是基于 MPP,所以不能”断点续传“

Hive 和 Impala 是批处理,Spark 是流处理,streaming

你可能感兴趣的:(大数据,大数据,hadoop,hive,impala,mapreduce)