【数据仓库】hive on Tez配置
hive on Tez 搭建
前提是hive4.0+hadoop3.2.2数仓已搭建完成,现在只是更换其执行引擎 为Tez。搭建可参考【数据仓库】hive + hadoop数仓搭建实践文章。
Tez 下载
下载地址
https://archive.apache.org/dist/tez/
官网地址
https://tez.apache.org/releases/apache-tez-0-10-3.html
这里使用Tez0.10.3版本,下载地址:
https://archive.apache.org/dist/tez/0.10.3/apache-tez-0.10.3-bin.tar.gz
安装配置
# 解压
tar -zxvf apache-tez-0.10.3-bin.tar.gz
# 改名
mv apache-tez-0.10.3-bin tez-0.10.3
在hive/conf/hive_env.sh,增加如下配置:
export TEZ_HOME=/home/datahouse/tez-0.10.3
export TEZ_JARS=""
for jar in `ls $TEZ_HOME | grep jar`; do
export TEZ_JARS=$TEZ_JARS:$TEZ_HOME/$jar
done
for jar in `ls $TEZ_HOME/lib`; do
export TEZ_JARS=$TEZ_JARS:$TEZ_HOME/lib/$jar
done
#export HIVE_AUX_JARS_PATH=/opt/modules/hadoop/share/hadoop/common/hadoop-lzo-0.4.20.jar$TEZ_JARS
export HIVE_AUX_JARS_PATH=$TEZ_JARS
HIVE_AUX_JARS_PATH的配置不能少,不然hive启动时无法找到tez的包,这个配置变量就是用来加载hive以外的第三方包的。
在hive/conf下新建tez-site.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>tez.lib.uris</name>
<value>${fs.defaultFS}/tez/tez-0.10.3,${fs.defaultFS}/tez/tez-0.10.3/lib</value>
</property>
<property>
<name>tez.lib.uris.classpath</name>
<value>${fs.defaultFS}/tez/tez-0.10.3,${fs.defaultFS}/tez/tez-0.10.3/lib</value>
</property>
<property>
<name>tez.use.cluster.hadoop-libs</name>
<value>true</value>
</property>
<property>
<name>tez.history.logging.service.class</name>
<value>org.apache.tez.dag.history.logging.ats.ATSHistoryLoggingService</value>
</property>
</configuration>
由于配置的是hdfs路径,需要将tez上传到hdfs上
su hadoop
# 在hdfs 文件系统中建 tez目录
hdfs dfs -mkdir /tez
# 上传 tez 到 建的目录上去
hdfs dfs -put /home/datahouse/tez-0.10.3 /tez
修改conf 下的 hive-site.xml配置:
<property>
<name>hive.execution.engine</name>
<value>tez</value>
</property>
重启hive 相关服务。报错如下:
日志jar包冲突,将tez 下的 日志包移除。
注意,hdfs上的也要移除。
重启hiveserver2,继续报错
2024-12-30 11:24:00: Starting HiveServer2
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/fs/BatchListingOperations
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:411)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:370)
at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
at org.apache.hadoop.fs.FileSystem.loadFileSystems(FileSystem.java:3289)
at org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:3334)
at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:3373)
at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:125)
at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:3424)
at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:3392)
at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:485)
at org.apache.hadoop.fs.Path.getFileSystem(Path.java:365)
at org.apache.hadoop.hive.common.FileUtils.getJarFilesByPath(FileUtils.java:1319)
at org.apache.hadoop.hive.conf.HiveConf.initialize(HiveConf.java:6565)
at org.apache.hadoop.hive.conf.HiveConf.<init>(HiveConf.java:6447)
at org.apache.hadoop.hive.common.LogUtils.initHiveLog4jCommon(LogUtils.java:96)
at org.apache.hadoop.hive.common.LogUtils.initHiveLog4j(LogUtils.java:80)
at org.apache.hive.service.server.HiveServer2.main(HiveServer2.java:1274)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.hadoop.util.RunJar.run(RunJar.java:323)
at org.apache.hadoop.util.RunJar.main(RunJar.java:236)
Caused by: java.lang.ClassNotFoundException: org.apache.hadoop.fs.BatchListingOperations
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 38 more
报错问题是找不到类,Exception in thread “main” java.lang.NoClassDefFoundError: org/apache/hadoop/fs/BatchListingOperations
这类问题其实解决起来有个通用思路,类找不到,无非就是相关的jar包版本不匹配,导致在使用这个类的地方在对应的jar包里找不到。
通过错误栈可以得知:hiveserve2在启动时,调用了org.apache.hadoop.hive.common.FileUtils.getJarFilesByPath方法,该方法调用了org.apache.hadoop.fs.Path.getFileSystem方法继而执行到org/apache/hadoop/fs/BatchListingOperations找不到类了。去hive-common-4.0.jar包中找到了org.apache.hadoop.hive.common.FileUtils.getJarFilesByPath函数调用位置,在hive-common4.0.jar包下的pom文件中,看到了引用的hadoop-common的jar包,hive 安装目录下未找到该包,去hadoop安装目录下,找到了该包的hadoop-common-3.2.jar版本,查看源码,找不到org/apache/hadoop/fs/BatchListingOperations类,所以会报这个错误。下面将hadoop-common-3.2.jar换成了hadoop-common-3.3.jar版本,能找到org/apache/hadoop/fs/BatchListingOperations类,但是又报错找不到org/apache/hadoop/fs/LeaseRecoverable类,于是继续更换到hadoop-common-3.4.jar版本,能找到org/apache/hadoop/fs/LeaseRecoverable类。但是metastore服务启动又报缺jar包了。更换更新的包,但问题却越来越多了。这一切都是引入tez 后造成的,引入tez后,hive的执行逻辑需要hadoop的包,与实际环境中hadoop的包不匹配。经过搜索,找到了官网hive4.0版本下tez的配置。但是hadoop版本得升级到hadoop3.3.6。然后基于hadoop3.3.6去集成tez,替换hadoop的MR。
hive 4.0版本的tez集成
由于hive4.0 + hadoop 3.2.1版本的数仓在集成tez时,会引起hive 依赖包 和hadoop包的版本不匹配,所以在升级hadoop3.2.1到3.3.6后,按照官网教程配置tez。hadoop3.3.6版本升级参考【数据仓库】hadoop3.3.6 安装配置
版本搭配为hive 4.0 + hadoop 3.3.6+tez0.10.3
官网参考文档
https://hive.apache.org/docs/latest/manual-installation_283118363/
tez包的下载解压就不说了,按上文操作,下面直接讲配置:
tez 配置
# tez
export TEZ_HOME=/home/datahouse/tez-0.10.3
export PATH=$PATH:$TEZ_HOME/*:$TEZ_HOME/conf
conf/tez-site.xml文件增加配置(在tez安装目录下)
<configuration>
<property>
<name>tez.lib.uris</name>
<value>${fs.defaultFS}/tez/tez-0.10.3,${fs.defaultFS}/tez/tez-0.10.3/lib</value>
</property>
<property>
<name>tez.lib.uris.classpath</name>
<value>${fs.defaultFS}/tez/tez-0.10.3,${fs.defaultFS}/tez/tez-0.10.3/lib</value>
</property>
<property>
<name>tez.use.cluster.hadoop-libs</name>
<value>true</value>
</property>
<property>
<name>tez.history.logging.service.class</name>
<value>org.apache.tez.dag.history.logging.ats.ATSHistoryLoggingService</value>
</property>
</configuration>
这里tez.lib.uris配置了hdfs分布式文件系统上的路径,还要记得将相关的包传上去,参考上面的脚本。
etc/hadoop/hadoop-env.sh文件增加配置(在hadoop安装目录)
# tez
export TEZ_CONF=/home/datahouse/tez-0.10.3/conf
export TEZ_JARS=/home/datahouse/tez-0.10.3
export HADOOP_CLASSPATH=${TEZ_CONF}:${TEZ_JARS}/*:${TEZ_JARS}/lib/*:${HADOOP_CLASSPATH}
conf/hive-site.xml文件增加配置(在hive安装目录)
<configuration>
<property>
<name>hive.tez.container.size</name>
<value>1024</value>
</property>
<property>
<name>hive.execution.engine</name>
<value>tez</value>
</property>
<property>
<name>tez.lib.uris</name>
<value>${fs.defaultFS}/tez/tez-0.10.3,${fs.defaultFS}/tez/tez-0.10.3/lib</value>
</property>
<property>
<name>tez.configuration</name>
<value>/home/datahouse/tez-0.10.3/conf/tez-site.xml</value>
</property>
<property>
<name>tez.use.cluster.hadoop-libs</name>
<value>true</value>
</property>
</configuration>
启动hive相关服务,即可启动tez引擎。
测试验证
通过hivesql执行如下语句:
select count(*) from t_people where provice = '河南省' and age>30;
使用MR执行时间为48 s 942 ms
切换到tez执行时间为13 s 449 ms
可见速度快了很多。
hive查询优化
在BI中连接hive ,即使使用了tez,在拖了2个图表时,再拖第三个时,数据加载就会变慢,甚至超时。下面对探究hive 配置优化。
<!--开启hive 并行执行能力-->
<property>
<name>hive.exec.parallel</name>
<value>true</value>
</property>
<!--设置tez任务的并行度-->
</property>
<property>
<name>tez.task.parallelism</name>
<value>4</value>
</property>
<!--设置并行执行的线程数-->
<property>
<name>hive.exec.parallel.thread.number</name>
<value>20</value>
</property>
加上上述参数后,虽然不超时了,但查询依旧很慢,看来hive数仓在对接BI指标时速度还是不及mysql,因为指标表里都是计算好的指标数据,数据量并没有那么大的,要是接入BI,加载这么慢,那肯定是无法满足业务要求的。看来hive在作为数仓存储和分析数据后生成结果数据,在展示时还是得通过mysql表进行呈现。
经验
1 数仓相关的框架在搭建时,对每个组件的版本是有匹配要求的,否则会各种找不到类的错误;
2 使用组件配置遇到问题时,记得去官网找相关参考资料;
3 hive on Tez 模式可以提高hive数据处理分析的速度,但在BI场景加载速度还是不能满足要求;