解决执行 spark.sql 时版本不兼容的一种方式

news2024/10/6 14:34:41

场景描述

hive 数据表的导入导出功能部分代码如下所示,使用 assemble 将 Java 程序和 spark 相关依赖一起打成 jar 包,最后 spark-submit 提交 jar 到集群执行。

public class SparkHiveApplication {

    public static void main(String[] args){

        long start = System.currentTimeMillis();
        String writeSql = "";
        SparkConf sparkConf = new SparkConf();

        for (String arg : args) {
            if (arg.startsWith("WriteSql=")) {
                writeSql = arg.replaceFirst("WriteSql=", "");
            }
        }

        SparkSession spark = SparkSession
                .builder()
                .appName("write data to hive table")
                .config(sparkConf)
                .enableHiveSupport()
                .getOrCreate();

        // LOAD DATA LOCAL INPATH '/path/to/file.csv' INTO TABLE target_table PARTITION (field='x')
        spark.sql(writeSql);

        long end = System.currentTimeMillis();
        System.out.println("cost time:" + (end - start));
    }
}
  <dependency>
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-hive_2.11</artifactId>
      <version>2.4.8</version>
  </dependency>

在CDH6.3.2 集群(后面称CDH),当程序执行 spark.sql 导入本地磁盘 csv 数据到 hive 表时出现异常(如下),但导出表数据到本地磁盘、从 HDFS 导入导出功能却都是正常的。

Caused by: java.lang.IllegalArgumentException: Wrong FS: file:/input/data/training/csv_test1_1301125633652294217_1690451941587.csv, expected: hdfs://nameservice1
        at org.apache.hadoop.fs.FileSystem.checkPath(FileSystem.java:649)

查资料判定是 spark-hive_2.11 版本不兼容导致的,在调试的过程中陆续又出现异常(如下)

Exception in thread "main" org.apache.spark.sql.AnalysisException: org.apache.hadoop.hive.ql.metadata.HiveException: Unable to fetch table csv_test2. Invalid method name: 'get_table_req';
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/hive/ql/metadata/HiveException
        at java.lang.Class.getDeclaredConstructors0(Native Method)

最终使用 spark-hive_2.1.1: 2.4.0-cdh6.3.3 解决了最初的本地磁盘导入异常。

接着用包含 spark-hive_2.1.1: 2.4.0-cdh6.3.3 依赖的 jar 包在 CDP 集群(另一个大数据集群)执行导入导出时又抛了异常,修改依赖版本为 spark-hive_2.11: 2.4.8 ,异常解决。

java.lang.NoSuchMethodException: org.apache.hadoop.hive.ql.metadata.Hive.alterTable(java.lang.String, org.apache.hadoop.hive.ql.metadata.Table, org.apache.hadoop.hive.metastore.api.EnvironmentContext)

此时两个集群中参与导入导出的部分组件版本如下:

集群sparkhiveJava 中的 spark-hive_2.1
CDH3.0.x2.1.12.4.0-cdh6.3.3
CDP3.0.x3.1.32.4.8

备注:导入导出操作采用 spark on k8s 方式执行,所以使用是镜像中的 spark 3.0 而非 CDH 、CDP 集群上安装的 spark。

异常原因分析

spark.sql 执行时要做三件事情:

  1. spark 首先创建 hiveMetaStoreClient 对象;
  2. 再调用 hiveMetaStoreClient 的方法去跟 CDH(CDP) 中的 hiveMetastoreServer 通信获取表相关元信息。
  3. 根据获取到的信息生成 sql 的执行计划,真正处理数据。

生成对象 jvm 首先需要通过全限定类名找到对应 Class 文件,通过反射的方式构造出对象再执行对象方法。问题也在这个地方:包名+类名相同,不同版本可能方法名、方法参数、方法内容不同,对应的出现 Invalid method name: 'get_table_req' java.lang.NoSuchMethodException 以及方法执行时抛出异常。

场景描述中更换依赖版本实际上是在找适配的 hiveMetastore 版本,并且让 jvm 率先加载到。2.4.0-cdh6.3.3 内部包含 hive-metastore:2.1.1-cdh6.3.3,2.4.8内部包含 hive-metastore:1.2.1spark2。

另一种解决方式

spark1.4.0 以后的版本支持和不同版本的 Hive Metastore 交互。列表贴的是 spark 3.4.1 兼容的 hive meatstore 版本 0.12.0 到 2.3.9 和 3.0.0 到 3.1.3。不同版本兼容可在官方文档查看。

在这里插入图片描述

怎么配置和不同版本 hive metastore 交互?

(1)内置。spark 内置了 hive,如果应用程序 jar 包中也没有带,也没有外部指定时,默认使用内置的。不同版本 spark 内置的 hive 版本也有差异,spark3.4.1 内置 hive2.3.9,spark3.0.3 内置 hive2.3.7。在 spark-shell 中使用 spark.sql 时应该用的是内置的,因为那会没有 Java jar 包,启动也仅仅是在命令行敲了“spark-shell”。

(2)当场下载。配置spark.sql.hive.metastore.version=2.1.1 spark.sql.hive.metastore.jars=maven ,当执行spark.sql 时会先从 maven 仓库下载 2.1.1 相关的依赖到本地 /root/.livy/jars 路径下,大概 188 个 jar 包,总大小 200M 左右。但这种方式当网速很慢或者 maven 仓库没有某些依赖时会下载失败,而且当场下载也不适合生产环境。

(3)指定版本以及依赖的路径。

  • spark 3.1.0 之前配置 spark.sql.hive.metastore.version=2.1.1 spark.sql.hive.metastore.jars=/path-to-hive-jars/* 。执行 spark.sql 时就会率先从 path-to-hive-jars 路径下寻找依赖。
  • spark 3.1.0 之后需要配置 spark.sql.hive.metastore.version=2.1.1 spark.sql.hive.metastore.jars=pathspark.sql.hive.metastore.jars.path=path-to-hive-jars。“path-to-hive-jars” 可以是 HDFS 上的路径,具体细节看表格介绍。

​ 这种方式可以用在生产环境中。

如果采用方式(3)怎么提前获取到正确的依赖,既能跟 spark 兼容又能和集群 hive 通信没问题?

要操作哪个集群如果该集群 hive 在 spark 版本兼容的范围内。直接将集群 hive/lib 下的全部 jar 包(200M左右)“怼” 给 spark 就可以了。(可能用不了那么多,但筛选需要做实验测试)。

下面是在 CDH 集群执行导入操作时的 spark-submit 命令。提前将 CDH 的 hive/lib 下的 jar 包拿出来挂载到容器的 /opt/ml/input/data/training/sparkjar/hive-jars 路径下。

#  在 k8s 容器中执行
/usr/local/spark/bin/spark-submit \
--conf spark.driver.bindAddress=172.16.0.44 \
--deploy-mode client \
--conf spark.sql.hive.metastore.jars=/data/training/sparkjar/hive-jars/* \
--conf spark.sql.hive.metastore.version=2.1.1 \
--properties-file /opt/spark/conf/spark.properties \
--class com.spark.SparkHiveApplication \
local:///data/training/sparkjar/hive-metastore-spark-app-jar-with-dependencies.jar \
WriteSql=TE9BRCBEQVRBIExPQ0FMIElOUEFUSCAnL29wdC9tbC9vdXRwdXQvMTc1NjQ2NDY2MDY3Mzk4NjU3LzE3NTY0NjQ2NjA2NzM5ODY1Ny9wYXJ0LTAwMDAwLWVhYjA2ZWZiLTcwNTktNGI4MS04YmRhLWE3NGE5Yzg3OTY2MS1jMDAwLmNzdicgSU5UTyBUQUJMRSBkdF90aW9uZV90ZXN0XzIwMjIwNzIyIHBhcnRpdGlvbiAocGFydF9udW09JzEnKQ==

与工程结合时肯定能获取到全部 jar 包以及找到合适的“怼”方式。这里列举的只是一种向 spark 任务添加依赖的方式。

尝试打“瘦”包

在创建 assembly jar 的时候,将 spark-hive_2.1 的生命周期设置为 provided,即不将该依赖打入最后的 jar 包。因为在运行 jar 任务时集群管理器可以自己提供依赖的 jar。而且 spark-hive 在 maven 官网的生命周期就被给定是 provided。

没有 spark-hive 依赖的 jar 包大小 9M (之前是 144M),分别在 CDP 和 CDH 上执行导入导出操作。结果:

  • CDP 集群测试通过。

  • CDH 集群异常。猜测是原生 spark3 和 hive-metastore:2.1.1-cdh6.3.3 不兼容(发行版有时会在原生基础上做改动),改用方式(3)中的配置后导入导出功能正常。

如果集群采用发行版部署,大版本下各组件兼容的可能性更大些。而且当频繁调试 Java jar 功能时 9M 大小缩短了上传时间,效率也变高了。

小结

通过配置的方式可以指定 spark 使用的 hiveMetastore。优先使用集群自带的依赖可以在一定程度上减少组件不兼容异常。Java jar 包中只管应用程序怎么写,依赖让集群提供,可以解除 jar 包与某个大数据集群的强绑定关系。但外部配置只是一种解决方案,如果要与工程结合还需要根据场景需求进一步设计实现方案并做实验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/893543.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Dubbo—核心优势

一、快速易用 无论你是计划采用微服务架构开发一套全新的业务系统&#xff0c;还是准备将已有业务从单体架构迁移到微服务架构&#xff0c;Dubbo 框架都可以帮助到你。Dubbo 让微服务开发变得非常容易&#xff0c;它允许你选择多种编程语言、使用任意通信协议&#xff0c;并且…

什么是低价治理服务

当商品的销售价低于品牌要求的建议价时&#xff0c;就会被认为是低价销售&#xff0c;销售的主体是店铺&#xff0c;那店铺的运营方就成了低价的主导者&#xff0c;低价行为大部分品牌都会跟进&#xff0c;低价店铺的信息品牌也会去收集&#xff0c;因为只有掌握了低价链接、低…

什么是 脏写,脏读,幻读,不可重复读?怎样能解决这四种问题?

我们通过如下语句先创建一个 student 学生表。我就以对学生表的操作来解释什么是脏写&#xff0c;脏读&#xff0c;幻读&#xff0c;不可重复读 创建完成之后随便插入一条数据 1. 脏写&#xff1f; 对于两个事务 SessionA&#xff0c;SessionB&#xff0c;如果SessionA修改了另…

无公网IP,公网SSH远程访问家中的树莓派教程

文章目录 前言 如何通过 SSH 连接到树莓派步骤1. 在 Raspberry Pi 上启用 SSH步骤2. 查找树莓派的 IP 地址步骤3. SSH 到你的树莓派步骤 4. 在任何地点访问家中的树莓派4.1 安装 Cpolar内网穿透4.2 cpolar进行token认证4.3 配置cpolar服务开机自启动4.4 查看映射到公网的隧道地…

Timeplate Definition

timeplate定义描述单个tester cycle&#xff0c;并指定所有event edges被放置在cycle的位置。 必须在引用之前定义所有的timeplates。一个procedure必须有至少一个timeplate定义&#xff0c;所有的时钟必须在timeplate定义中进行定义&#xff0c;timeplate的定义有以下格式&am…

C++ STL关联式容器(详解)

STL关联式容器 C STL关联式容器是什么&#xff1f; 在《C STL容器》一节中讲到&#xff0c;C 容器大致分为 2 类&#xff0c;即序列式容器和关联式容器。其中&#xff0c;序列式容器&#xff08;包括 array、vector、list、deque 和 forward_list&#xff09;已经在前面章节中…

【校招VIP】前端JS语言考点之Vue考察

考点介绍&#xff1a; Vue是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是&#xff0c;Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层&#xff0c;不仅易于上手&#xff0c;还便于与第三方库或既有项目整合。另一方面&#xff0c;当与现代化的工具…

我的编程语言学习笔记

前言 作为一名编程初学者&#xff0c;我深知学习编程需要不断积累和记录。在这篇博客文章中&#xff0c;我将分享一些我在学习C/C编程语言过程中记录的常用代码、特定函数、复杂概念以及特定功能。希望能与大家一起切磋进步&#xff01; 常用代码&#xff1a; 1. 输入输出操作…

19----C/C++之加密解密带空格字符串的读入

本文主要通过一道题目来讲解C语言相关的简单加密和解密&#xff0c;以及如何读入带有空格的字符串 小试牛刀 题目描述 在情报传递过程中&#xff0c;为了防止情报被截获&#xff0c;往往需要对情报用一定的方式加密。我们给出一种最简单的加密方法&#xff0c;对给定的一个字…

【爬虫练习之glidedsky】爬虫-基础1

题目 链接 爬虫的目标很简单&#xff0c;就是拿到想要的数据。 这里有一个网站&#xff0c;里面有一些数字。把这些数字的总和&#xff0c;输入到答案框里面&#xff0c;即可通过本关。 思路 找到调用接口 分析response 代码实现 import re import requestsurl http://www.…

冠达管理:印花税是什么意思?港股取消印花税是利好还是利空?

在股票市场上&#xff0c;投资者买卖股票需求交纳必定的手续费用&#xff0c;比如&#xff0c;佣钱费用、过户费用、印花税等等&#xff0c;那么&#xff0c;印花税是什么意思&#xff1f;港股撤销印花税是利好仍是利空&#xff1f;下面冠达管理为大家准备了相关内容&#xff0…

QT处理日志文件

由于实际生产需要&#xff0c;软件系统的运行&#xff0c;会产生大量的日志文件&#xff0c;有时候一天就能产生超过百万条log记录&#xff0c;那么为了能够处理日志文件&#xff0c;查询并且找到我们想要的报错信息&#xff0c;因此不得不考虑怎么实现&#xff0c;打开大日志文…

excel日期函数篇2

1、DATE(year,month,day)&#xff1a;根据年、月、日三个数值返回其表示的日期 2、DATEVALUE(date_text)&#xff1a;返回由文本字符串表示的日期的十进制数字 处理时间的时候&#xff0c;如果得到的是字符串格式&#xff0c;要将其转换为日期进行相关操作。excel函数里是使用文…

MinGW编译运行报错RTTI symbol not found for class ‘XXX‘

最近在调试程序时莫名的出现图中报错&#xff1a; 还遇到过for class QObject&#xff0c;在此记录一下&#xff0c;排查后发现&#xff0c;原因都是有资源被重复释放导致的。

intelij idea 2023 创建java web项目

1.点击New Project 2.创建项目名称为helloweb &#xff0c;jdk版本这里使用8&#xff0c;更高版本也不影响工程创建 点击create 3.新建的工程是空的&#xff0c;点击File-> Project Structure 4.点击Modules 5.点击加号&#xff0c;然后键盘输入web可以搜索到web模块&…

69 # 强制缓存的配置

强制缓存 强制缓存&#xff1a;以后的请求都不需要访问服务器&#xff0c;状态码为 200协商缓存&#xff1a;每次都判断一下&#xff0c;告诉是否需要找缓存&#xff0c;状态码为 304 默认强制缓存&#xff0c;不缓存首页&#xff08;如果已经断网&#xff0c;那这个页面应该…

Python三行代码实现json转Excel

最近重保&#xff0c;经常需要通过Excel上报威胁事件。安全设备的告警很多都是json格式的&#xff0c;就需要将json转成Excel。 用Python将json转成excel也就三行代码的事&#xff0c;先将json串导入形成字典对象&#xff0c;再通过pandas转成DataFrame直接输出excel。 实现如下…

windows电脑系统自带的画图工具如何实现自由拼图

1.首先选中你要拼接的第一张图片&#xff0c;右键选着编辑&#xff0c;会自动打开自带的画图工具 然后就是打开第一张图片&#xff0c;如下图所示 接着就是将画布托大&#xff0c;如下图所示。 然后点击选择&#xff0c;选择下面的空白区域&#xff0c;选着区域的范围要比准备拼…

智能楼宇综合布线实训室建设方案

一、楼宇智能综合布线实训室方案概述 楼宇智能综合布线实训室方案旨在为学生提供一个真实的学习和实践环境&#xff0c;以培养他们在楼宇智能综合布线领域的实际操作能力和技能。以下是一个概述&#xff1a; 1. 培养目标&#xff1a;培养学生在楼宇智能综合布线方面的综合能力…

耳朵小戴哪种耳机,佩戴舒适度最好的骨传导蓝牙耳机分享

亲爱的小伙伴们&#xff01;这些精心挑选的骨传导耳机绝对能给你带来全新的耳机体验。告别堵塞的耳道和细菌的困扰&#xff0c;让音乐与你完美融合&#xff01;不管你是运动爱好者、音乐发烧友还是生活达人&#xff0c;这些骨传导耳机都能满足你的需求。快行动起来&#xff0c;…