繁体   English   中英

如何使Spark Streaming DStream作为SQL表

[英]How to Make Spark Streaming DStream as SQL table

目的如下:

  • 每隔N秒使用Spark Streaming从Socket读取数据

  • 将接收到的数据注册为SQL表

  • 从HDFS等读取的数据将更多,它们将作为参考数据被注册为SQL表

  • 这个想法是对合并的流和参考数据执行任意SQL查询

请参见下面的代码片段。 我看到数据是从forEachRDD循环的“内部”写出到磁盘的,但是当在forEachRDD循环的“外部”写的时候,相同的注册SQL表的数据为空。

请提出您的意见/建议以解决此问题。 也欢迎实现上述“目标”的任何其他机制。

case class Record(id:Int, status:String, source:String)

object SqlApp2 {
  def main(args: Array[String]) {
    val sparkConf = new SparkConf().setAppName("SqlApp2").setMaster("local[2]")
    val sc = new SparkContext(sparkConf)
    val sqlContext = new SQLContext(sc)
    // Create the streaming context with a 10 second batch size
    val ssc = new StreamingContext(sc, Seconds(10))

    val lines = ssc.socketTextStream("localhost", 9999, StorageLevel.MEMORY_AND_DISK_SER)

    var alldata:DataFrame=sqlContext.emptyDataFrame
    alldata.registerTempTable("alldata")

    lines.foreachRDD((rdd: RDD[String], time: Time) => {
      import sqlContext.implicits._

      // Convert RDD[String] to DataFrame
      val data = rdd.map(w => {
        val words = w.split(" ")
        Record(words(0).toInt, words(1), words(2))}).toDF()

      // Register as table
      data.registerTempTable("alldata")
      data.save("inside/file"+System.currentTimeMillis(), "json", SaveMode.ErrorIfExists)  // this data is written properly
    })

    val dataOutside = sqlContext.sql("select * from alldata")
    dataOutside.save("outside/file"+System.currentTimeMillis(), "json", SaveMode.ErrorIfExists) // this data is empty, how to make the SQL table registered inside the forEachRDD loop visible for rest of application

    ssc.start()
    ssc.awaitTermination()
  }

感谢和问候

MK

我的理解是,除非您采用“ 结构化流”路由,否则只能在“ foreachRDD”之类的块中创建表。 通过这种方法,您可以使用滑动窗口在表中保留一定数量的数据。 我在下面给出了相关代码。

// You could create a window of 1 minute to run your query
val windowedStream = lines.window(Seconds(60))

windowedStream.foreachRDD((rdd: RDD[String], time: Time) => {
  import sqlContext.implicits._
  val data = rdd.map(w => {
    val words = w.split(" ")
    Record(words(0).toInt, words(1), words(2))
  }).toDF()
  data.createOrReplaceTempView("alldata")

  // You can read your other data source and convert it into a DF table
  // and join with the 'alldata' table
  val dataInside = sqlContext.sql("select * from alldata")
  dataInside.show()
})

希望这可以帮助。

请注意,结构化流媒体尚处于初始阶段,其功能非常有限。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM