将RDD保存为JSON文件的问题,考虑到每个RDD的大小永远不会超过10 Mb

时间:2017-02-03 11:31:35

标签: json apache-spark amazon-s3 spark-streaming

我正在使用Spark Streaming从Kafka读取JSON字符串的DStream。我需要以JSON格式保存S3上的输入数据。这就是我这样做的方式,但是当批处理中的数据量大约为5Mb时,执行此代码需要很长时间。可以优化吗? 我需要将数据保存在JSON文件(*.json)中,因为还有另一个程序使用这些文件并按如下方式读取它们:

var df = sqlContext.read.json("s3n://" + bucketNameData + "/" + directoryS3 + "/*.json")

因此,为了将RDD保存为sinlge JSON文件,我尝试了rdd.map(lambda x :json.loads(x)) .coalesce(1, shuffle=True).saveAsTextFile('examples/src/main/resources/demo.json'),但它以一种荒谬的方式保存数据,据我所知,我希望以后能够将它们读作我在上面显示(从json文件中获取df)。因此我切换到amazonS3Client,但我觉得它可能会被优化。也许我应该将rdd转换为DataFrame左右,然后以某种方式将其保存为JSON?

val mySet = ssc.sparkContext.broadcast(Map("metadataBrokerList"->metadataBrokerList,
                                           "bucketNameData"->bucketNameData,
                                           "bucketNameCode"->bucketNameCode))

dstreamdata.foreachRDD(rdd => {
      if (!rdd.isEmpty()) {
      rdd.foreachPartition { iter =>
        val producer = UtilsTest.createProducer(mySet.value("metadataBrokerList"))
        val amazonS3Client = UtilsTest.createS3()
        iter.foreach { msg =>
          if (msg.nonEmpty) {
            // Save messages to S3
            val CONTENT_TYPE = "application/json"
            val fileContentBytes = msg.getBytes(StandardCharsets.UTF_8)
            val fileInputStream = new ByteArrayInputStream(fileContentBytes)
            val metadata = new ObjectMetadata()
            metadata.setContentType(CONTENT_TYPE)
            metadata.setContentLength(fileContentBytes.length)
            val datetime = Calendar.getInstance.getTime
            val formatter = new SimpleDateFormat("yyyy-MMM-dd-HH-mm-ss")
            val setID = formatter.format(datetime)
            val filePath = mySet.value("bucketNameData") + "/file_" + setID + ".json"
            val putObjectRequest = new PutObjectRequest(mySet.value("bucketNameData"), filePath, fileInputStream, metadata)
            amazonS3Client.putObject(putObjectRequest)

//---

1 个答案:

答案 0 :(得分:0)

你的直接putObject()会更高效,因为通常用于提交工作的rename()中没有副本。在处理失败和重播工作时,您可能会遇到问题。

如果使用newHadooopRDD,可以使用提交算法2显着降低开销:

import os import pyautogui, pyautoguiFix mouseSpeed = 0.5 # click icon on memu desktop pyautogui.moveTo(1271, 379, duration= mouseSpeed) pyautoguiFix.click()