参考:
guava源码 : https://github.com/google/guava
guava包冲突: https://superuser.com/questions/1492421/i-cant-run-hive-in-command-line
guava 更新: https://issues.apache.org/jira/browse/HADOOP-15960
hive版本: https://hive.apache.org/general/downloads/
tez官网: https://tez.apache.org/
tez-0.10.1安装文档: https://github.com/apache/tez/blob/branch-0.10.1/docs/src/site/markdown/install.md
tez-timeline: https://github.com/apache/tez/blob/branch-0.10.1/docs/src/site/markdown/tez_yarn_timeline.md
hive on Tez : https://hive.apache.org/docs/latest/hive-on-tez_33296197/
llap文档: https://hive.apache.org/docs/latest/llap_62689557/
llap设计文档: https://issues.apache.org/jira/secure/attachment/12665704/LLAPdesigndocument.pdf
https://www.cnblogs.com/boanxin/p/13336930.html
https://hive.apache.org/docs/latest/llap_62689557/
https://www.cnblogs.com/lanston/p/13868096.html
https://www.cnblogs.com/muzhongjiang/p/13181917.html
Tez
Tez是Apache最新的支持DAG作业的开源计算框架,它可以将多个有依赖的task转换为一个task
从而大幅提升DAG作业的性能。Tez并不直接面向最终用户——事实上它允许开发者为最终用户构建性能更快、扩展性更好的应用程序。Hadoop传统上是一个大量数据批处理平台。但是,有很多用例需要近乎实时的查询处理性能。还有一些工作则不太适合MapReduce,例如机器学习。Tez的目的就是帮助Hadoop处理这些用例场景。
Tez产生的背景
Tez构建在Yarn之上,后者是Hadoop所使用的新资源管理框架。Tez产生的主要原因是绕开MapReduce所施加的限制
。除了必须要编写Mapper
和Reducer
的限制之外,中间进行 Shuffle 缓存到HDFS。在Hive中,查询需要对不相关的key进行多次shuffle操作的场景非常普遍,例如join – grp by – window function – order by。
MR性能差,资源消耗大
,如:Hive作业之间的数据不是直接流动的,而是借助HDFS作为共享数据存储系统,即一个作业将处理好的数据写入HDFS,下一个作业再从HDFS重新读取数据进行处理。很明显更高效的方式是,第一个作业直接将数据传递给下游作业
,这就引出了tez的DAG架构。
Tez 和MR的区别
mapReduce在map和reduce阶段都会产生I/O落盘
。但是Tez就不要这一步骤了。目前hive使用了Tez(Hive是一个将用户的SQL请求翻译为MR任务,最终查询HDFS的工具Tez采用了DAG(有向无环图)来组织MR任务
。
核心思想:将Map任务和Reduce任务进一步拆分,Map任务拆分为Input-Processor-Sort-Merge-Output
,Reduce任务拆分为Input-Shuffer-Sort-Merge-Process-output
,Tez将若干小任务灵活重组,形成一个大的DAG作业
。 Tez与oozie不同:oozie只能以MR任务为整体来管理、组织,本质上仍然是多个MR任务的执行,不能解决上面提到的多个任务之间硬盘IO冗余的问题。 Tez只是一个Client,部署很方便。
Tez的原理
Application Master Pool
初始化AM池。Tez先将作业提交到AMPoolServer服务上。AMPoolServer服务启动时就申请多个AM,Tez提交作业会优先使用缓冲池资源。
Container Pool
AM启动时会预先申请多个Container。
Tez 的工作流程
- 用户提交查询:用户通过 Hive 提交查询。
- Hive 解析与优化查询:Hive 将查询转换为抽象语法树并生成
逻辑执行计划
。 - 生成 Tez DAG 并提交:Hive 将查询转化为
Tez DAG
,并提交给 Tez 引擎。 - Tez 任务调度:Tez 向 YARN 请求资源,YARN 分配计算资源(容器)给 Tez 任务,运行
物理执行计划(AM+Container)
。 - Tez 执行任务:Tez 任务开始执行,并通过 HDFS 进行数据读取和写入。任务间的结果通过内存交换,避免磁盘 I/O。
- YARN 释放资源:任务完成后,YARN 释放资源,供其他任务使用。
- Hive 返回结果:查询结果返回给用户,或者存储在 HDFS 中。
版本选择
如果使用原生版本进行部署时,需要着重调研hadoop、hive、tez的版本,因为guava
、jetty
、protobuf
等包很容易冲突:
https://superuser.com/questions/1492421/i-cant-run-hive-in-command-line
https://issues.apache.org/jira/browse/HADOOP-15960
tez安装
tez安装主要是编译
、配置
、依赖的处理
。
编译
这里建议自己编译,因为可以指定hadoop 的依赖版本,取消不想编译的冲突包等。
下载源码:apache-tez-0.10.2-src
配置阿里云源
添加到pom文件中
<repositories>
<repository>
<id>aliyun-repos</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>aliyun-plugin</id>
<url>https://maven.aliyun.com/nexus/content/groups/public/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
修改pom文件
修改如下配置
#修改成自己的hadoop版本,我这里修改了
<hadoop.version>3.1.2</hadoop.version>
#注释掉tez-ui,后面单独处理
<!--<module>tez-ui</module>-->
然后执行命令编译:
mvn clean package -DskipTests=true -Dmaven.javadoc.skip=true
安装protobuf-3.19.4 ,不同版本的tez依赖不同版本的protobuf
,安装后:
protoc --version
配置
在tez 的安装目录,创建文件夹conf/
创建文件tez-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property>
<name>tez.lib.uris</name>
<value>/apps/tez/tez-0.10.1.tar.gz</value>
</property>
</configuration>
hadoop 中的tez配置:
# Tez引擎
export TEZ_CONF_DIR=/opt/tez/conf/tez-site.xml
export TEZ_JARS=/opt/tez/
export HADOOP_CLASSPATH=${TEZ_CONF_DIR}:${TEZ_JARS}/*:${TEZ_JARS}/lib/*
上传tez到hdfs
hadoop fs -mkdir /apps/tez-x.y.z-SNAPSHOT
hadoop fs -copyFromLocal tez-dist/target/tez-x.y.z-SNAPSHOT.tar.gz /apps/tez-x.y.z-SNAPSHOT/
- 将步骤 2 中创建的 tez minimal 解压到本地目录(假设 TEZ_JARS 是下一步解压文件的位置)。
tar -xvzf tez-dist/target/tez-x.y.z-minimal.tar.gz -C $TEZ_JARS
依赖处理
实际运行时可能有很多的依赖问题,比如:
- 启动hive报错
- hive起不来
- Tez 的example 案例可以运行 但是hive提交任务就会报错
- 提交后找不到类,或直接报类冲突。
等等,当出现包冲突时需要按照自己的需求按情况处理
比如hive 中的jetty比较落后,依赖的jetty也比较多,导致启动过程中报jett的3 版本和4版本的包冲突的问题。
可以将hadoop中现有的高版本的jetty复制到hivelib下,然后没有的jar包,在maven上下载上传。
❗❗❗不要随便删除任何依赖,有的教程提示删除log4J的依赖包,这个视版本而定,有的只是提示有WARN冲突,并不影响,删除这种依赖可能照成未知的问题,比如容器异常退出但是没有任何的stdout和stderr日志,很折磨人。
hive官网配置:data/conf/llap/hive-site.xml
配置类:org.apache.hadoop.hive.conf.HiveConf
启动TimeLine
启动timelineserver
yarn timelineserver
运行测试
set hive.execution.engine=tez;set mapreduce.job.queuename=big;
----------------------------------------------------------------------------------------------
VERTICES MODE STATUS TOTAL COMPLETED RUNNING PENDING FAILED KILLED
----------------------------------------------------------------------------------------------
Map 1 .......... container SUCCEEDED 1 1 0 0 0 0
Reducer 2 ...... container SUCCEEDED 1 1 0 0 0 0
----------------------------------------------------------------------------------------------
VERTICES: 02/02 [==========================>>] 100% ELAPSED TIME: 11.06 s
----------------------------------------------------------------------------------------------
可以看到运行在container中
tez-ui
UI模块不是必须的,自己感兴趣的可以在后面单独编译
http://hadoop01:8888/tez-ui/#/
Tez-LLAP
LLAP概念
LLAP是hive 2.0.0版本引入的新特性,hive官方称为Live long and process
,为了促进缓存和 JIT 优化,并消除大部分启动成本,守护程序在集群上的 worker 节点上运行。守护程序处理 I/O、缓存和查询片段执行。
- 这些节点是无状态的。 对 LLAP 节点的任何请求都包含数据位置和元数据。它处理本地和远程位置;locality 是调用方的责任 (YARN)。
- 恢复/弹性。 故障和恢复得到了简化,因为任何数据节点仍可用于处理输入数据的任何片段。因此,Tez AM 可以简单地在集群上重新运行失败的片段。
- 节点之间的通信。 LLAP 节点能够共享数据(例如,获取分区、广播片段)。这是通过 Tez 中使用的相同机制实现的。
参考 https://www.cnblogs.com/zackstang/p/10573642.html
使用 LLAP 执行的示例: Tez AM 整体编排执行。 查询的初始阶段被推送到 LLAP,大型shuffle在自己的容器中执行。多个查询和应用程序可以并发访问 LLAP。
LLAP既可以在yarn中启动,也可以单独运行。
LLAP安装
使用hive生成llap运行目录
添加到hive-site.xml中
<property>
<name>hive.llap.execution.mode</name>
<value>all</value>
</property>
<!-- 有这四个auto, none, all, map选项,表示是否在llap或者container里运行查询,all表示让所有的task都在llap进程内执行-->
<property>
<name>hive.execution.mode</name>
<value>llap</value>
</property>
<!-- 两个选项[container, llap],表示查询运行在container或者llap-->
<property>
<name>hive.llap.daemon.service.hosts</name>
<value>@llap_service</value>
</property>
<!-- llap_service是启动llap服务的时候 name指定的名字,可根据情况来设置-->
<property>
<name>hive.zookeeper.quorum</name>
<value>hadoop01:2181,hadoop02:2181,hadoop03:2181,hadoop04:2181,hadoop04:2181</value>
</property>
<property>
<name>hive.llap.daemon.memory.per.instance.mb</name>
<value>15600</value>
</property>
<!-- LlapDaemon内存,需要在这里指定,hive service instances指定遇到过失败-->
<!-- LlapDaemon core数-->
<!--如下是HiveServer2的参数,用来启用llap的并发查询-->
<property>
<name>hive.server2.tez.default.queues</name>
<value>root.storm</value>
</property>
<property>
<name>hive.server2.tez.initialize.default.sessions</name>
<value>true</value>
</property>
<property>
<name>hive.server2.tez.sessions.per.default.queue</name>
<value>2</value>
</property>
执行,会生成llap程序:
hive --service llap --name llap_service --instances 5 --size 25g --loglevel INFO --cache 10g --executors 10 --iothreads 10 --args " -XX:+UseG1GC -XX:+ResizeTLAB -XX:+UseNUMA -XX:-ResizePLAB"
替换的过程中会出现python的语法问题,可以修改脚本解决。
单独进程运行
关于单独进程启动的相关没有任何文档,只能在源码中寻找,参考源码说明:llap-server/changes_for_non_slider_install.txt
配置llap-daemon-site.xml
<configuration>
<!--单独线程的 LLAP-->
<property>
<name>hive.execution.mode</name>
<value>llap</value>
</property>
<property>
<name>hive.llap.daemon.work.dirs</name>
<value>/opt/hive/bin/llap-yarn-14Jan2025</value>
</property>
<property>
<name>hive.llap.daemon.service.hosts</name>
<value>hadoop01,hadoop02,hadoop04,hadoop05</value>
</property>
<property>
<name>hive.llap.daemon.rpc.port</name>
<value>39589</value>
</property>
<property>
<name>hive.zookeeper.quorum</name>
<value>hadoop01:2181,hadoop02:2181,hadoop03:2181,hadoop04:2181,hadoop05:2181</value>
</property>
<property>
<name>hive.llap.daemon.num.executors</name>
<value>20</value>
</property>
<property>
<name>hive.llap.daemon.memory.per.instance.mb</name>
<value>25600</value>
</property>
<property>
<name>hive.llap.daemon.xmx.headroom</name>
<value>80%</value>
</property>
</configuration>
环境配置:llap-server/bin/llap-daemon-env.sh
我是直接shell执行:
export LLAP_DAEMON_HOME=/opt/hive/bin/llap-yarn-14Jan2025
export LLAP_DAEMON_USER_CLASSPATH=/opt/tez
export LLAP_DAEMON_BIN_HOME=/opt/hive/bin/llap-yarn-14Jan2025/bin
export LLAP_DAEMON_CONF_DIR=/opt/hive/bin/llap-yarn-14Jan2025/conf
export LLAP_DAEMON_HEAPSIZE=30720
启动llap
./llapDaemon.sh start
hive配置
在hive中也配置上启动llap 的节点,重启
<property>
<name>hive.execution.mode</name>
<value>llap</value>
</property>
<property>
<name>hive.llap.daemon.work.dirs</name>
<value>/opt/hive/bin/llap-yarn-14Jan2025</value>
</property>
<property>
<name>hive.llap.daemon.service.hosts</name>
<value>hadoop01,hadoop02,hadoop03,hadoop04,hadoop05</value>
</property>
<property>
<name>hive.llap.daemon.rpc.port</name>
<value>39589</value>
</property>
<property>
<name>hive.zookeeper.quorum</name>
<value>hadoop01:2181,hadoop02:2181,hadoop03:2181,hadoop04:2181,hadoop05:2181</value>
</property>
<property>
<name>hive.llap.daemon.num.executors</name>
<value>20</value>
</property>
<property>
<name>hive.llap.daemon.memory.per.instance.mb</name>
<value>25600</value>
</property>
hive执行:
#切换tez引擎
set hive.execution.engine=tez;set mapreduce.job.queuename=big;
# 选择llap模式
set hive.llap.execution.mode=all;
测试
测试tez和MR的性能
使用官方的demo跑一下测试
hadoop jar tez-examples-0.10.2.jar orderedwordcount /input /output
如果MR任务没问题,并且demo运行没问题,一般tez和hadoop环境就OK了,如果这步之后使用hive运行SQL 后报错,就很有可能是 tez 和 hive之间的问题,包依赖、包冲突问题。
在未做任何优化的前提下,3亿条数据:
--- 分别使用MR和Tez引擎测试查询速度
set hive.execution.engine=mr;
set hive.execution.engine=tez;
select count(*) from user_obs;
select * from user_obs where id =29999998;
--- MR
db> select count(*) from user_obs
[2024-12-10 21:31:17] 在 56 s 561 ms (execution: 56 s 474 ms, fetching: 87 ms) 内检索到从 1 开始的 1 行
--- MR
db> select * from user_obs where id =29999998
[2024-12-10 21:39:03] 在 58 s 654 ms (execution: 58 s 541 ms, fetching: 113 ms) 内检索到从 1 开始的 1 行
--- 使用Tez
db> select count(*) from user_obs
[2024-12-10 21:32:31] 在 29 s 175 ms (execution: 29 s 145 ms, fetching: 30 ms) 内检索到从 1 开始的 1 行
--- 使用Tez
db> select * from user_obs where id =29999998
[2024-12-10 21:37:50] 在 42 s 199 ms (execution: 42 s 148 ms, fetching: 51 ms) 内检索到从 1 开始的 1 行
可以看出明显比MR要快。
3亿条数据
通过程序生成3亿条数据
create table user_obs(
id int,
first_name string,
last_name string,
gender char(1),
careers int
)row format delimited fields terminated by '\t'
location '/hive/user_obs';
1 鲍77vrJ YuzFB M 23
2 邬NkdVK vwgL4 F 40
3 曹7dfIH b5Cuz M 57
set tez.am.resource.memory.mb=20480;
set tez.task.resource.memory.mb=1024m;
set tez.am.launch.cmd-opts=-Xmx15360m;
测试tez-llap性能
SQL | MapReduce | Tez | Tez LLAP |
---|---|---|---|
SELECT count(*) FROM user_obs; | 【1次】75.59 【2次】65.10 【3次】66.85 |
【1次】15.6 【2次】6.11 【3次】15.57 |
【1次】33.67 【2次】2.54 【3次】2.08 |
SELECT count(*) FROM user_obs WHERE gender = ‘M’; | 【1次】69.88 【2次】71.88 【3次】67.01 |
【1次】53.71 【2次】16.39 【3次】6.04 |
【1次】15.81 【2次】7.67 【3次】2.65 |
SELECT gender, COUNT(*) AS count, AVG(careers) AS avg_careers FROM user_obs GROUP BY gender; | 【1次】87.67 【2次】108.68 【3次】89.08 |
【1次】23.54 【2次】22.81 【3次】23.3 |
报错 |
SELECT u1.id, u1.first_name, u2.last_name FROM user_obs u1 JOIN user_obs u2 ON u1.id = u2.id WHERE u1.gender = ‘F’ limit 100; |
【1次】305.6 【2次】 【3次】 |
【1次】197.64 【2次】 【3次】 |
报错 |
测试中发现group by 等会导致内存打满,后续优化解决
其他
这里会持续更新tez、llap相关的一些奇怪的问题。
${yarn.app.container.log.dir} 路径问题
在安装Tez时,遇到yarn Application直接运行失败,但是没有任何日志信息,考虑到可能报错是tez的 container中报错,但是没有任何输出,十分的头疼,这时候无意间我在yarn的本地缓存目录:/data/hadoop/nodemanager/logs/…中,找到一个奇怪的目录'${yarn.app.container.log.dir}'
,这一看就是没有解析,随后到tez源码中,找到了这个配置:
是位于tez-dag中:src/main/resources/tez-container-log4j.properties
这个log4J的配置,我尝试在tez-site.xml中覆盖,但是没有成功,所以只能在源码编译的时候固定为一个目录:/var/log/yarn/container/syslog
,之后我在这个目录中获取到了极其关键的包冲突日志。
llap的安装配置等问题
我最开始直接运行script目录下llapDaemon.sh ,但是提示缺少很多包,我并没有找到任何关于llap 的包,后来我尝试将hive的lib加入到llap的classpath中,但是很多包有冲突。
配置启动llap mode 时,hive官网只提供了比较老的 SLIDER on YARN 部署
,并没有提供单独的process 部署,这部分的知识只能去源码中寻找:
在hive源码中很容易找到 llap-server/changes_for_non_slider_install.txt 规定了llap独立运行的配置:
-- 将 LLAP 作为 YARN 外部的独立守护程序运行,而不是作为 YARN 服务运行所需的更改列表不完整
hive.llap.daemon.work.dirs - 在每个节点上创建目录,并设置为此值。
hive.llap.daemon.service.hosts - 将运行 llap 的主机的逗号分隔列表。
ApplicationConstants.Environment.CONTAINER_ID 应该在安全集群的环境中可用
随后我又在script、bin目录找到了关键的环境配置信息:
我找到了各种针对环境的配置,应该是由env.sh 加载环境变量, 并由llapDaemon.sh启动。虽然我在hive的script/llap下找到了这个目录,但当我配置一些参数时:例如LLAP_DAEMON_CONF_DIR
、LLAP_DAEMON_HOME
我根本没有头绪。script目录下看上去不是一个程序目录,这时想到了之前在一个帖子中看到有生成llap程序的命令,所以试了下:
https://www.cnblogs.com/muzhongjiang/p/13181917.html
(我的python版本可能不兼容,因此对package.py 做了很多改动,注释掉一些chmod 校验和为print添加括号)
运行后在这个目录生成一个tar.gz,这个目录本来是将这个程序通过Yarnfile运行在yarn上的,但我并不想那么做。
因此我解压了tar.gz包,得到一个看上去是我想要的目录,我直接手动配置:
export LLAP_DAEMON_HOME=/opt/hive/bin/llap-yarn-14Jan2025
export LLAP_DAEMON_USER_CLASSPATH=/opt/tez
export LLAP_DAEMON_BIN_HOME=/opt/hive/bin/llap-yarn-14Jan2025/bin
export LLAP_DAEMON_CONF_DIR=/opt/hive/bin/llap-yarn-14Jan2025/conf
export LLAP_DAEMON_HEAPSIZE=30720
运行后完美启动!
希望这篇文章能被浏览器索引并帮助到您😊
网络上关于tez 相关不是很活跃,可以直接留言,沟通交流