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

场景描述

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://nameservice1at 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/HiveExceptionat 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.rhkb.cn/news/100550.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

操作系统——shell编程

文章目录 shell入门什么是 Shell&#xff1f;Shell 编程的 Hello World Shell 变量Shell 编程中的变量介绍Shell 字符串入门Shell 字符串常见操作Shell 数组 Shell 基本运算符算数运算符关系运算符逻辑运算符布尔运算符字符串运算符文件相关运算符 shell流程控制if 条件语句for…

市面上那里有稳定L2股票行情数据接口?

随着市场的发展和技术的进步&#xff0c;level2股票行情数据接口已经成为股票交易软件的标准配置之一。虽然这些券商软件的功能在很大程度上相似&#xff0c;但它们仍然有自己的特点和优势。 例如&#xff1a;通过股票交易所以其专业的研究报告和丰富的信息服务而受到广泛关注&…

Shell编程基础02

0目录 1.case语法 2.grep 3.sed 4.awk 5.linux安装mysql 1.case语法 创建一个txt文档 执行 查询用户名 case 用法 写一个计算器脚本 加入函数 补充查看进程命名 2.find grep命令 Find 查询当前目录下 以sh结尾的文件 Grep 查询义开头的 或者加入正则表达…

Java --- 二维数组

一、二维数组的定义 public class TwoArrayTest {public static void main(String[] args) {//二维数组声明与初始化//方式1&#xff1a;静态初始化int[][] arr new int[][]{{1,2,3},{1,2,3},{1,2,3}};//方式2&#xff1a;动态初始化int[][] arr2 new int[3][3];arr2[0][1] …

开学季有哪些电容笔值得买吗?便宜的电容笔推荐

开学有哪些电容笔值得入手呢&#xff1f;这款名为Apple Pencil的平替电容笔&#xff0c;在压感功能方面这一项上&#xff0c;与Apple Pencil相比的主要区别就是&#xff0c;平替电容笔仅仅只拥有倾斜的压感功能&#xff0c;但用来书写和做笔记还是绰绰有余的&#xff0c;价格便…

C++系列-引用

引用 引用的基本使用引用的起源引用的语法引用的本质引用的注意事项引用和指针 引用作为函数参数引用作为函数的返回值常量引用其它用返回值方式调用函数&#xff08;case 1&#xff09;用函数的返回值初始化引用的方式调用函数&#xff08;case 2&#xff09;用返回引用的方式…

探工业互联网的下一站!腾讯云助力智造升级

引言 数字化浪潮正深刻影响着传统工业形态。作为第四次工业革命的重要基石&#xff0c;工业互联网凭借其独特的价值快速崛起&#xff0c;引领和推动着产业变革方向。面对数字化时代给产业带来的机遇与挑战&#xff0c;如何推动工业互联网的规模化落地&#xff0c;加速数字经济…

【Axure模板】APP帮助中心原型,在线客服意见反馈模块高保真原型

作品概况 页面数量&#xff1a;共 10 页 兼容软件&#xff1a;Axure RP 9/10&#xff0c;不支持低版本 应用领域&#xff1a;原型设计模板 作品申明&#xff1a;页面内容仅用于功能演示&#xff0c;无实际功能 作品特色 该模板作品为APP帮助与客服的通用模块&#xff0c;…

MySQL分页查询-性能优化

MySQL分页查询优化 一、背景二、原因三、解决四、原理探究 https://blog.csdn.net/hollis_chuang/article/details/130570281 一、背景 业务背景&#xff1a;给C端10万级别的用户&#xff0c;同时发送活动消息&#xff0c;活动消息分为6类。数据背景&#xff1a;mysql表有百万…

拒绝摆烂!C语言练习打卡第五天

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;每日一练 &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、选择题 &#x1f4dd;1.第一题 &#x1f4dd;2.第二题 &#x1f4d…

【高级IO】- 多路转接之 poll | epoll

目录 I/O多路转接 - poll poll 函数 poll 服务器 poll 服务器 poll 的优点 poll 的缺点 I/O 多路转接 - epoll epoll 的相关系统调用 epoll_create 函数 epoll_ctl 函数 epoll_wait 函数 epoll 工作原理 epoll 服务器 ​编辑 epoll 的优点&#xff08;与 sele…

在线零售供应链管理:从0到100

全球57%的公司将其供应链视为竞争优势&#xff0c;然而只有6%的人表示完全了解它。无论您是首次在线卖家还是经验丰富的专业人士&#xff0c;驾驭管理高效且具有成本效益的零售供应链的复杂性都可能具有挑战性。一起来了解一下吧&#xff01; 供应链管理是什么&#xff1f;它基…

html动态爱心代码【二】(附源码)

目录 前言 效果演示 内容修改 完整代码 总结 前言 七夕马上就要到了&#xff0c;为了帮助大家高效表白&#xff0c;下面再给大家带来了实用的HTML浪漫表白代码(附源码)背景音乐&#xff0c;可用于520&#xff0c;情人节&#xff0c;生日&#xff0c;表白等场景&#xff0c…

前端打开弹窗时将链接转化为二维码

qrcodejs2 1.安装qrcodejs2 2.在使用页面中引入 import QRCode from "qrcodejs2";3.在组件中注册(Vue2项目) components: {QRCode,}, 4.在data中定义qrcode&#xff0c;以及方法中使用 showCode(row) {this.dialogVisible true;this.$nextTick(() > { 需要n…

21 移动测试神器:带你玩转Appium

Appium特点 Appium 作为目前主流的移动应用自动化测试框架&#xff0c;具有极强的灵活性&#xff0c;主要体现在以下 5 个方面&#xff1a; 测试用例的实现支持多种编程语言&#xff0c;比如 Java、Ruby、Python 等&#xff1b; Appium Server 支持多平台&#xff0c;既…

算法基础(1):排序和查找算法

1、排序算法 1.1、堆排序(大顶堆)-重点&#xff1a; 参考文章&#xff1a;堆排序1、堆排序二 前置知识&#xff1a; 大顶堆&#xff1a;完全二叉树&#xff0c;且父节点大于左右儿子&#xff0c;左右子树又是大顶堆&#xff0c;依赖数组来实现(vector)第一个节点的父节点&…

QT中按钮的基类QAbstractButton

QT中按钮的基类QAbstractButton 关于控件类的学习方法继承关系信号槽函数标题和图标按钮的 Check 属性 关于控件类的学习方法 控件类很多&#xff0c;API更多&#xff0c;但是不需要记忆知道控件对应的类名&#xff0c;通过帮助文档随用随查优先看帮助文档中控件对应的信号和槽…

LeetCode算法心得——k-avoiding 数组的最小总和(标记数组)

大家好&#xff0c;我是晴天学长&#xff0c;这是一个细节题和一部分的思维题哈&#xff01; 2) .算法思路 k-avoiding 数组的最小总和 1,填充一个1到n 的Boolean的数组 要n个数&#xff0c;但是数组大小不能确定。 所以建立1000的大小。 2.遍历筛选&#xff0c;如果数组中有这…

ubuntu18.04安装远程控制软件ToDest方法,针对官网指令报错情况

有时我们在家办公&#xff0c;需要控制实验室的笔记本&#xff0c;因此好用的远程控制软件会让我们的工作事半功倍&#xff01; 常用的远程控制软件有ToDesk&#xff0c;向日葵&#xff0c;以及TeamViewer&#xff0c;但是为感觉ToDesk更流畅一些&#xff0c;所以这里介绍一下…

MySQL之索引和事务

索引什么是索引索引怎么用索引的原理 事务使用事务事务特性MySQL隔离级别 索引 什么是索引 索引包含数据表所有记录的引用指针&#xff1b;你可以对某一列或者多列创建索引和指定不同的类型&#xff08;唯一索引、主键索引、普通索引等不同类型&#xff1b;他们底层实现也是不…