Spark java.io.NotSerializableException

文章目录

    • 源代码
    • 错误原因
    • 错误信息
    • 方案一
      • 方案一具体代码
    • 方案二
      • 方案二具体代码

源代码

//编写SQL语句
val sql = "insert into province_browser_cnt(`province`,`browser`,`operator_cnt`) values(?,?,?)"
//获取mysql的连接
val conn = JDBCUtil.getConn()
//将如下的结果写入数据库
userRDD.map(line => ((line(6), line(7)), 1))
  .reduceByKey(_ + _)
  .foreach(line=> {
    //创建ps
    val ps = conn.prepareStatement(sql)
    ps.setString(1, line._1._1) //设置省份
    ps.setString(2, line._1._2) //设置浏览器
    ps.setInt(3, line._2) //设置统计值
    //提交
    ps.execute()
  })

错误原因

因为ps是一个PrepareStatement对象,这个对象无法序列化,而传入foreach中的对象是需要分布式传送到各个节点上,传送前先序列化,到达相应服务器上后再反序列化,PrepareStatement是个Java类,如果一个Java类想(反)序列化,必须实现Serialize接口,PrepareStatement并没有实现这个接口。

错误信息

Exception in thread "main" org.apache.spark.SparkException: Task not serializable
	at org.apache.spark.util.ClosureCleaner$.ensureSerializable(ClosureCleaner.scala:403)
	at org.apache.spark.util.ClosureCleaner$.org$apache$spark$util$ClosureCleaner$$clean(ClosureCleaner.scala:393)
	at org.apache.spark.util.ClosureCleaner$.clean(ClosureCleaner.scala:162)
	at org.apache.spark.SparkContext.clean(SparkContext.scala:2326)
	at org.apache.spark.rdd.RDD$$anonfun$foreach$1.apply(RDD.scala:971)
	at org.apache.spark.rdd.RDD$$anonfun$foreach$1.apply(RDD.scala:970)
	at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:151)
	at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:112)
	at org.apache.spark.rdd.RDD.withScope(RDD.scala:385)
	at org.apache.spark.rdd.RDD.foreach(RDD.scala:970)
	at edu.nanzhi.core.useraction.UserActionExternalPro$.main(UserActionExternalPro.scala:68)
	at edu.nanzhi.core.useraction.UserActionExternalPro.main(UserActionExternalPro.scala)
Caused by: java.io.NotSerializableException: com.mysql.cj.jdbc.DatabaseMetaData
Serialization stack:
	- object not serializable (class: com.mysql.cj.jdbc.DatabaseMetaData, value: com.mysql.cj.jdbc.DatabaseMetaData@59c70ceb)
	- field (class: com.mysql.cj.jdbc.ConnectionImpl, name: dbmd, type: interface java.sql.DatabaseMetaData)
	- object (class com.mysql.cj.jdbc.ConnectionImpl, com.mysql.cj.jdbc.ConnectionImpl@210d2a6c)
	- field (class: edu.nanzhi.core.useraction.UserActionExternalPro$$anonfun$main$18, name: conn$1, type: interface java.sql.Connection)
	- object (class edu.nanzhi.core.useraction.UserActionExternalPro$$anonfun$main$18, <function1>)
	at org.apache.spark.serializer.SerializationDebugger$.improveException(SerializationDebugger.scala:40)
	at org.apache.spark.serializer.JavaSerializationStream.writeObject(JavaSerializer.scala:46)
	at org.apache.spark.serializer.JavaSerializerInstance.serialize(JavaSerializer.scala:100)
	at org.apache.spark.util.ClosureCleaner$.ensureSerializable(ClosureCleaner.scala:400)
	... 11 more

方案一

添加collect()函数将结果数据收集到driver端。对象ps在driver端,collect后的数据也在driver端,就不需ps序列化数据传到各个节点了,因此就不会出现序列化错误。

方案一具体代码

userRDD.map(line => ((line(6), line(7)), 1))
  .reduceByKey(_ + _)
  .collect()
  .foreach(line=> {
    //创建ps
    val ps = conn.prepareStatement(sql)
    ps.setString(1, line._1._1) //设置省份
    ps.setString(2, line._1._2) //设置浏览器
    ps.setInt(3, line._2) //设置统计值
    //提交
    ps.execute()
  })

如上代码改正后将不会再报序列化错误。

方案二

因为方案一采用collect(),如果数据量大,将会消耗大量Driver端内存,影响整个作业性能,严重者甚至会导致Driver宕掉,导致整个作业失败。所以建议采用分区循环方式foreachPartition实现。foreachPartition函数和foreach函数类似,foreachPartition是将rdd的每一个分区循环一次,而foreach函数是上游每行数据循环一次。foreachPatition可以将每个分区的数据以迭代器方式迭代操作,而foreach函数则不能,通常foreachPatition比foreach要高效。比如,将RDD中的所有数据通过JDBC连接写入数据库,如果使用foreach函数,可能要为每一个元素都创建一个connection,这样开销很大,如果使用foreachPartition,那么只需要针对每一个分区建立一个connection。同时,foreachPartitioin可以迭代进行处理,但foreach里的对象仍然还是需要反序列化。

方案二具体代码

userRDD.map(line => ((line(6), line(7)), 1))
  .reduceByKey(_ + _)
  .foreachPartition(it => {
    val conn = JDBCUtil.getConn()
    try {
      //获取ps对象
      val ps = conn.prepareStatement(sql)
      //链接自动提交关闭
      conn.setAutoCommit(false)
      //循环迭代器
      it.foreach(line => {
        ps.setString(1, line._1._1) //设置省份
        ps.setString(2, line._1._2) //设置浏览器
        ps.setInt(3, line._2) //设置统计值
        //提交
        ps.addBatch()
      })
      //循环完后批次执行
      ps.executeBatch()
      //链接提交--->手动提交必须要关闭自动提交,默认事自动提交
      conn.commit()
    }
  })

如上代码改正后将不会再报序列化错误,同时比方案一更加高效。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

河道采砂执法监管信息化平台:科技赋能,智慧监管

随着信息技术的飞速发展&#xff0c;信息化平台已经成为提升行业监管效率和水平的重要工具。河道采砂作为水利资源管理的重要环节&#xff0c;其执法监管同样需要与时俱进&#xff0c;利用先进技术手段提升监管效能。河道采砂执法监管信息化平台便是这一背景下的产物&#xff0…

某酒业集团数字化转型规划(169页附下载)

某酒业集团数字化转型项目实施方案建议书(P169).rar是一个极具参考价值的资料&#xff0c;它详细地阐述了如何利用数字化技术来推动企业转型。这份建议书以IBM的先进技术和某酒业集团的实际应用需求为基础&#xff0c;提出了一套全面、系统的数字化转型解决方案。该方案首先对某…

在linux系统打开pycharm,为pycharm在桌面设置图标

1.打开终端输入&#xff1a;gedit /usr/share/applications/Pycharm.desktop 然后会弹出一个文件 2.在文件中写入&#xff1a; [Desktop Entry] TypeApplication NamePycharm GenericNamePycharm3 CommentPycharm3:The Python IDE Execsh /home/.../pycharm.sh #自己pych…

【kettle002】kettle访问人大金仓KingbaseES数据库并处理数据至execl文件

一直以来想写下基于kettle的系列文章&#xff0c;作为较火的数据ETL工具&#xff0c;也是日常项目开发中常用的一款工具&#xff0c;最近刚好挤时间梳理、总结下这块儿的知识体系。 熟悉、梳理、总结下人大金仓KingbaseES数据库相关知识体系 kettle访问人大金仓KingbaseES数据库…

Centos之yum安装好玩的命令

1.会动的小火车 我在root下使用的 yum install sl.x86_64sl2.figlet yum install figlet.x86_64figlet 55553.cowsay会说话 yum install cowsay

javaScript基础3

javaScript 一.对象1.概念2.创建对象的三种方法(1).字面量创建&#xff08;利用{}&#xff09;(2)变量、属性、函数、方法的区别(3).new Object创建(4).构造函数 3.new关键字的执行过程4.遍历对象&#xff08;for..in) 二.内置对象1.了解2.math对象3.日期对象&#xff08;构造函…

【声呐仿真】学习记录0.5-配置ssh远程连接docker、在docker中使用nvidia显卡

【声呐仿真】学习记录0.5-配置ssh远程连接docker、在docker中使用nvidia显卡 配置ssh远程连接docker1.端口映射2.配置ssh 在docker中使用nvidia显卡配置CUDA 注意&#xff1a;之前已经创建过容器的&#xff0c;需要打包成镜像&#xff0c;重新创建容器&#xff0c;因为要在创建…

伐木机不要石头!!!

伐木机不要石头&#xff01;&#xff01;&#xff01;(easy version) 本题有对应的hard version&#xff0c;区别仅在多次询问中。保证easy version的测试用例集是hard version的真子集&#xff0c;通过困难版本的代码经过简单修改可直接通过简单版 看着家里贫瘠的资源&#x…

【Python学习】面向对象

面向对象 1.初识对象1.1 生活中数据的组织1. 2 程序中数据的组织1.3 使用对象组织数据1.4进行对比 2. 成员方法2.1 类的定义和使用2.2 成员变量和成员方法2.2.1 成员变量2.2.2 成员方法的定义语法2.2.3 self 的作用 3. 类和对象3.1 面向过程3.2 面向对象 4.构造方法4.1 属性成员…

用Vue做一个待办事项

这个待办事项有以下功能&#xff1a;增删查&#xff0c;既新增待办事项&#xff0c;删除待办事项&#xff0c;查看全部&#xff0c;未完成&#xff0c;完成待办事项&#xff0c;当鼠标移动到待办事项上时会显示删除按钮 分为四个部分来实现&#xff1a;ToDoHeader.vue、ToDoMai…

XYCTF 部分wp及学习记录

1.ezmd5 根据题目提示 我们知道应该是要上传两张md5值相同的图片 根据原文链接&#xff1a;cryptanalysis - Are there two known strings which have the same MD5 hash value? - Cryptography Stack Exchange 把保存下来的图片上传一下 得到flag 2.ezhttp 根据原文链接&…

多臂老虎机介绍【Multi-armed Bandits】

强化学习笔记 主要基于b站西湖大学赵世钰老师的【强化学习的数学原理】课程&#xff0c;个人觉得赵老师的课件深入浅出&#xff0c;很适合入门. 第一章 强化学习基本概念 第二章 贝尔曼方程 第三章 贝尔曼最优方程 第四章 值迭代和策略迭代 第五章 强化学习实践—GridWorld 第…

Python基础05-数学运算与排列组合生成

在Python中进行数学运算和生成排列组合是数据科学、机器学习和日常编程中常见的任务。本文将介绍如何在Python中执行基本的数学运算、处理复数、使用数学函数、生成排列和组合、随机数生成、处理分数、统计函数以及处理无穷大和NaN值。 1. 基本算术运算 Python支持传统的四则…

26版SPSS操作教程(高级教程第十三章)

前言 #今日世界读书日&#xff0c;宝子你&#xff0c;读书了嘛~ #本期内容&#xff1a;主成分分析、因子分析、多维偏好分析 #由于导师最近布置了学习SPSS这款软件的任务&#xff0c;因此想来平台和大家一起交流下学习经验&#xff0c;这期推送内容接上一次高级教程第十二章…

【剪映专业版】05文字重叠

【剪映专业版】05文字重叠 1.在素材库中搜索纯黑背景&#xff0c;添加文本&#xff0c;设置合适的字体、字号等&#xff0c;导出备用。 2.返回窗口&#xff0c;设置字体颜色为纯黑&#xff0c;勾选描边设置描边为纯白&#xff0c;描边粗细值为8。导出备用。 3.将视频素材导入。…

SpringCloud系列(11)--将微服务注册进Eureka集群

前言&#xff1a;在上一章节中我们介绍并成功搭建了Eureka集群&#xff0c;本章节则介绍如何把微服务注册进Eureka集群&#xff0c;使服务达到高可用的目的 Eureka架构原理图 1、分别修改consumer-order80模块和provider-payment8001模块的application.yml文件&#xff0c;使这…

Win10 打开有些软件主界面会白屏不显示,其他软件都正常

环境&#xff1a; Win10专业版 英伟达4070 显卡 问题描述&#xff1a; Win10 打开有些软件主界面会白屏不显示,打开远程协助软件AIRMdesk,白色&#xff0c;其他软件都正常 解决方案&#xff1a; 网上说电脑没有接显示器独立显卡的关系导致 我是只有一台主机&#xff0c;没…

VUE3 ref,props,生命周期

1.--ref属性 1.1代码 1.1.1子表 <template><div class"person"><h1>中国</h1><h2 ref"title2">北京</h2><h3>尚硅谷</h3><button click"showLog">点我输出h2这个元素</button>&l…

海康智能相机FTP本地存图流程

背景&#xff1a;近期一个新项目需要使用到智能相机&#xff0c;借助智能相机算法直接输出检测结果并将相机图像进行本地化保存和展示。由于申购目标智能相机未到&#xff0c;暂时使用测试智能相机。 目标智能相机型号&#xff1a;海康智能相机MV-SC3050XC 当前测试相机型号…

MySQL主要内容

1&#xff0c;在表中插入数据 插入值的类型&#xff0c;必须和字段的类型保持一致 - 如果数据类型是字符串&#xff0c;必须引号引起来&#xff0c;数字的话&#xff0c;可以不加 - 插入的数据顺序和字段的顺序必须保持一致 格式一&#xff1a;向表中插入数据 insert in…
最新文章