Spark - 使用Firehose从分区文件夹中读取JSON

时间:2016-10-30 20:20:57

标签: apache-spark apache-spark-sql databricks spark-structured-streaming

Kinesis firehose将文件的持久性(在本例中为时间序列JSON)管理到由YYYY / MM / DD / HH划分的文件夹层次结构(直到24编号中的小时)......很棒。

如何使用Spark 2.0然后我可以读取这些嵌套的子文件夹并从所有叶子json文件创建一个静态Dataframe?数据框阅读器是否有“选项”?

我的下一个目标是将其作为流式传输DF,其中Firehose持久保存到s3中的新文件自然会成为使用Spark 2.0中新结构化流媒体的流数据帧的一部分。我知道这都是实验性的 - 希望有人之前使用S3作为流媒体文件源,其中数据被分成如上所述的文件夹。当然更喜欢直接使用Kinesis流,但是这个连接器上没有日期,所以Firehose-> S3是临时的。

ND:我正在使用数据库,它将S3安装到DBFS中,但当然可以很容易地成为EMR或其他Spark提供商。很高兴看到一个笔记本电脑,如果一个可分享的例子。

干杯!

2 个答案:

答案 0 :(得分:6)

  

我可以读取嵌套的子文件夹并从所有叶子JSON文件创建静态DataFrame吗? DataFrame阅读器有选项吗?

是的,因为您的目录结构是常规的(YYYY/MM/DD/HH),您可以使用下面的通配符字符给叶子节点提供路径

val spark: SparkSession = SparkSession.builder.master("local").getOrCreate

val jsonDf = spark.read.format("json").json("base/path/*/*/*/*/*.json")
// Here */*/*/*/*.json maps to YYYY/MM/DD/HH/filename.json 
  

当然,更喜欢直接使用Kinesis流,但是此连接器上没有2.0的日期,所以Firehose-> S3是临时的。

我可以看到Kinesis integration with Spark Streaming有一个图书馆。因此,您可以直接读取流数据并在其上执行SQL操作,而无需从S3读取。

groupId = org.apache.spark
artifactId = spark-streaming-kinesis-asl_2.11
version = 2.0.0

使用Spark Streaming和SQL

的示例代码
import org.apache.spark.streaming.Duration
import org.apache.spark.streaming.kinesis._
import com.amazonaws.services.kinesis.clientlibrary.lib.worker.InitialPositionInStream

val kinesisStream = KinesisUtils.createStream(
 streamingContext, [Kinesis app name], [Kinesis stream name], [endpoint URL],
 [region name], [initial position], [checkpoint interval], StorageLevel.MEMORY_AND_DISK_2)

kinesisStream.foreachRDD { rdd =>

  // Get the singleton instance of SparkSession
  val spark = SparkSession.builder.config(rdd.sparkContext.getConf).getOrCreate()
  import spark.implicits._

  // Convert RDD[String] to DataFrame
  val jsonDf = rdd.toDF() // or rdd.toDF("specify schema/columns here")

  // Create a temporary view with DataFrame
  jsonDf.createOrReplaceTempView("json_data_tbl")

  //As we have DataFrame and SparkSession object we can perform most 
  //of the Spark SQL stuff here
}

答案 1 :(得分:3)

完全披露:我为Databricks工作,但我不代表Stack Overflow。

  

如何使用Spark 2.0然后我可以读取这些嵌套的子文件夹并从所有叶子json文件创建一个静态Dataframe?有没有“选择”'到dataframe reader?

DataFrameReader支持加载序列。请参阅def json(paths: String*): DataFrame的文档。您可以指定序列,使用globbing模式或以编程方式构建它(推荐):

val inputPathSeq = Seq[String]("/mnt/myles/structured-streaming/2016/12/18/02", "/mnt/myles/structured-streaming/2016/12/18/03")
val inputPathGlob = "/mnt/myles/structured-streaming/2016/12/18/*"
val basePath = "/mnt/myles/structured-streaming/2016/12/18/0"
val inputPathList = (2 to 4).toList.map(basePath+_+"/*.json")
  

我知道这都是实验性的 - 希望有人之前使用S3作为流媒体文件源,其中数据被分区为如上所述的文件夹。当然更喜欢直接使用Kinesis流,但是这个连接器上没有日期,所以Firehose-> S3是临时的。

由于您正在使用DBFS,因此我假设已从Firehose传输数据的S3存储桶已经安装到DBFS。如果您需要帮助mounting your S3 bucket to DBFS,请查看Databricks文档。获得上述输入路径后,您只需将文件加载到静态或流数据帧中即可:

<强>静态

val staticInputDF = 
  spark
    .read
    .schema(jsonSchema)
    .json(inputPathSeq : _*)

staticInputDF.isStreaming
res: Boolean = false

<强>流

val streamingInputDF = 
  spark
    .readStream                       // `readStream` instead of `read` for creating streaming DataFrame
    .schema(jsonSchema)               // Set the schema of the JSON data
    .option("maxFilesPerTrigger", 1)  // Treat a sequence of files as a stream by picking one file at a time
    .json(inputPathSeq : _*)

streamingCountsDF.isStreaming
res: Boolean = true

大部分内容直接来自Databricks documentation on Structured Streaming。甚至还有一个笔记本示例,您可以直接导入Databricks。