我正在尝试使用Spark读取CVS文件,然后将其保存到Cassandra。当我使用琐碎的价值时,保存到Cassandra是有效的。
我有一个包含以下值的文件:
id,name,tag1|tag2|tag3
我想将它存储在cassandra表中:
id bigint, name varchar, tags set
我为此定义了一个案例类:
case class Item(id:Integer,name:String,tag:Set[String])
然后我使用这个表达式从CVS文件中获取RDD
val items = sc.textFile("items.csv").map(l => l.split(",") match {case Array (a,b,c) => Item(Integer.parseInt(a),b,c.split("\\|").toSet)})
当我现在为项目(开始处理)调用collect
或saveToCassandra
时,我收到以下错误:
org.apache.spark.SparkException: Job aborted due to stage failure: Task 1 in stage 29.0 failed 1 times, most recent failure: Lost task 1.0 in stage 29.0 (TID 38, localhost): scala.MatchError: [Ljava.lang.String;@6030bbe6 (of class [Ljava.lang.String;)
at $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$anonfun$2.apply(<console>:33)
at $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$anonfun$2.apply(<console>:33)
at scala.collection.Iterator$$anon$11.next(Iterator.scala:328)
at org.apache.spark.storage.MemoryStore.unrollSafely(MemoryStore.scala:249)
at org.apache.spark.CacheManager.putInBlockManager(CacheManager.scala:172)
at org.apache.spark.CacheManager.getOrCompute(CacheManager.scala:79)
at org.apache.spark.rdd.RDD.iterator(RDD.scala:242)
at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:61)
at org.apache.spark.scheduler.Task.run(Task.scala:64)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:203)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
答案 0 :(得分:2)
如上所述,问题在于拆分某些输入是生成一个数组,该数组少于或多于匹配中使用的3个元素。
但是,用于执行匹配的partialFuntion
可用于过滤做符合匹配条件的元素。 rdd.collect{partialFunction}
正是出于此目的:
val data = sc.textFile("items.csv")
val arrayData = data.map(l => l.split(","))
val items = arrayData.collect{case Array (a,b,c) => Item(Integer.parseInt(a),b,c.split("\\|").toSet)})
items.saveToCassandra(...)
rdd.collect{partialFunc}
(使用部分函数过滤/映射数据)不应与rdd.collect
混淆(将数据返回给驱动程序))答案 1 :(得分:1)
如果您的输入不是 3个条目的数组,则会出现匹配错误,例如
String("a,b").split(",") match {
case Array(a,b,c) => ....
}
因此我怀疑这是一些输入数据问题,您需要在match
中为其提供支持。
答案 2 :(得分:1)
我在下面使用它来保存CSV文件“ |”分离到cassandra DB。 希望这会有所帮助
package com
import java.io.FileInputStream
import java.util.Properties
import org.apache.log4j.LogManager
import org.apache.spark.{SparkConf, SparkContext}
object CsvLoad {
def main(args: Array[String]): Unit = {
val log = LogManager.getRootLogger
log.info("**********JAR EXECUTION STARTED**********")
val properties: Properties = new Properties
properties.load(new FileInputStream(args(0)))
val sparkConf = new SparkConf()
.setAppName(getClass.getName)
.set("spark.cassandra.connection.host", properties.getProperty("CASSANDRA_HOST"))
.set("spark.cassandra.connection.port", properties.getProperty("CASSANDRA_PORT"))
.setMaster("local[*]")
.set("spark.cassandra.auth.username", properties.getProperty("CASSANDRA_USERNAME"))
.set("spark.cassandra.auth.password", "Jcloud@1357")
.set("spark.cassandra.output.concurrent.writes", "32")
.set("spark.cassandra.output.consistency.level", "ONE")
.set("spark.cassandra.input.split.size_in_mb","67108864")
.set("spark.cassandra.output.batch.grouping.key", "none")
val sc=new SparkContext(sparkConf)
val spark = new org.apache.spark.sql.SQLContext(sc)
val data = spark.read.format("csv").option("header", "true").option("delimiter", "|").option("inferSchema", "true").
load("D:\\data.csv")
val output = data.write.format("org.apache.spark.sql.cassandra").options(Map("table" -> "mytable", "keyspace" -> "test", "cluster" -> "Test Cluster"))
output.save()
}
}