如何在执行程序上访问SparkContext以将DataFrame保存到Cassandra?

时间:2017-05-27 16:15:22

标签: java apache-spark apache-spark-sql spark-cassandra-connector

如何在执行者身上使用SparkContext(创建SparkSession或Cassandra会话)?

如果我将其作为参数传递给foreachforeachPartition,那么它将具有null值。我应该在每个执行者中创建一个新的SparkContext吗?

我要做的是如下:

读取包含数百万个XML文件的转储目录:

dumpFiles = Directory.listFiles(dumpDirectory)
dumpFilesRDD = sparkContext.parallize(dumpFiles, numOfSlices)
dumpFilesRDD.foreachPartition(dumpFilePath->parse(dumpFilePath))

parse()中,每个XML文件都使用Spark SQL进行验证,解析并插入到多个表中。只有有效的XML文件才会显示可以保存的相同类型的对象。在插入其中一个表之前,数据的一部分需要被其他键替换。

为了做到这一点,函数SparkContext中需要parse才能使用sparkContext.sql()

2 个答案:

答案 0 :(得分:2)

如果我改写你的问题,你想要的是:

  1. 阅读包含数百万个XML文件的目录
  2. 解析他们
  3. 将它们插入数据库
  4. 这是一个典型的提取,转换和加载(ETL)过程,它在Spark SQL中非常容易。

    可以使用单独的包spark-xml来加载XML文件:

      

    spark-xml 用于使用Apache Spark解析和查询XML数据的库,用于Spark SQL和DataFrame。结构和测试工具大多是从Spark Data的CSV数据源复制的。

    你可以安装"使用--packages命令行选项的包:

    $SPARK_HOME/bin/spark-shell --packages com.databricks:spark-xml_2.11:0.4.1
    

    引用spark-xml Scala API(使用SparkSession进行一些更改):

    // Step 1. Loading XML files
    val path = "the/path/to/millions/files/*.xml"
    val spark: SparkSession = ???
    val files = spark.read
      .format("com.databricks.spark.xml")
      .option("rowTag", "book")
      .load(path)
    

    这使得第一个要求几乎毫无疑问。您已经通过Spark SQL了解了百万个XML文件。

    第2步是解析行(来自XML文件)并标记要保存到适当表的行。

    // Step 2. Transform them (using parse)
    def parse(line: String) = ???
    val parseDF = files.map { line => parse(line) }
    

    您的parse函数可能会返回某些内容(作为主要结果)以及某些内容应保存到的表格。

    使用表格标记,您可以将parseDF拆分为每个表的DataFrame。

    val table1DF = parseDF.filter($"table" === "table1")
    

    等等(每张表)。

    // Step 3. Insert into DB    
    table1DF.write.option(...).jdbc(...)
    

    这只是你可能真正之后的概述,但这是一般的模式。将您的管道分解为可消化的块,并一次处理一个块。

答案 1 :(得分:1)

重要的是要记住,在Spark中,我们不应该根据执行者进行编程。

在Spark编程模型中,您的驱动程序主要是一个自包含的程序,其中某些部分将自动转换为物理执行计划。最终,一系列任务分布在工人/执行者之间。

当您需要为每个分区执行某些操作时,可以使用mapPartitions()之类的东西。有关详细信息,请参阅Spark : DB connection per Spark RDD partition and do mapPartition。请注意dbConnection对象如何包含在函数体中。

您不清楚参数的含义。如果只是数据(不是数据库连接或类似数据),我认为您需要使用boradcast variable