参考:

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

image.png|275
Tez是Apache最新的支持DAG作业的开源计算框架,它可以将多个有依赖的task转换为一个task从而大幅提升DAG作业的性能。Tez并不直接面向最终用户——事实上它允许开发者为最终用户构建性能更快、扩展性更好的应用程序。Hadoop传统上是一个大量数据批处理平台。但是,有很多用例需要近乎实时的查询处理性能。还有一些工作则不太适合MapReduce,例如机器学习。Tez的目的就是帮助Hadoop处理这些用例场景。
image.png|625

Tez产生的背景

Tez构建在Yarn之上,后者是Hadoop所使用的新资源管理框架。Tez产生的主要原因是绕开MapReduce所施加的限制。除了必须要编写MapperReducer的限制之外,中间进行 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,部署很方便。
image.png|750

Tez的原理

Application Master Pool 初始化AM池。Tez先将作业提交到AMPoolServer服务上。AMPoolServer服务启动时就申请多个AM,Tez提交作业会优先使用缓冲池资源。
Container Pool AM启动时会预先申请多个Container。
image.png|475

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 中。
    image.png|750

版本选择

如果使用原生版本进行部署时,需要着重调研hadoop、hive、tez的版本,因为guavajettyprotobuf 等包很容易冲突:
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/#/
image.png

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
image.png|575

使用 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的语法问题,可以修改脚本解决。

image.png|500

单独进程运行

关于单独进程启动的相关没有任何文档,只能在源码中寻找,参考源码说明: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

image.png|525

RPC端口:39589
webUI端口:15002
image.png|500

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亿条数据:
image.png

--- 分别使用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 等会导致内存打满,后续优化解决

image.png|475
image.png|500
image.png|500
image.png|500
image.png|500

其他

这里会持续更新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,之后我在这个目录中获取到了极其关键的包冲突日志。
image.png|525

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目录找到了关键的环境配置信息:
image.png

我找到了各种针对环境的配置,应该是由env.sh 加载环境变量, 并由llapDaemon.sh启动。虽然我在hive的script/llap下找到了这个目录,但当我配置一些参数时:例如LLAP_DAEMON_CONF_DIRLLAP_DAEMON_HOME 我根本没有头绪。script目录下看上去不是一个程序目录,这时想到了之前在一个帖子中看到有生成llap程序的命令,所以试了下:
https://www.cnblogs.com/muzhongjiang/p/13181917.html
(我的python版本可能不兼容,因此对package.py 做了很多改动,注释掉一些chmod 校验和为print添加括号)
运行后在这个目录生成一个tar.gz,这个目录本来是将这个程序通过Yarnfile运行在yarn上的,但我并不想那么做。
image.png
因此我解压了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

运行后完美启动!

希望这篇文章能被浏览器索引并帮助到您😊