sparkstreaming消费多个topic的数据写入不同的hive表

这几天有人问关于怎么把不同的topic的数据写入到hive的不同的表里,我写了一个简单的demo,大家可以参考一下,

package hive

import java.io.File
import org.apache.kafka.clients.consumer.ConsumerRecord
import org.apache.kafka.common.serialization.StringDeserializer
import org.apache.log4j.{Level, Logger}
import org.apache.spark.sql.{Row, SparkSession}
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.streaming.dstream.InputDStream
import org.apache.spark.streaming.kafka010.{ConsumerStrategies, KafkaUtils, LocationStrategies}

/**
  * spark消费多个topic的数据写入不同的hive表
  */
object SparkToHive {
  def main(args: Array[String]): Unit = {
    Logger.getLogger("org.apache.spark").setLevel(Level.WARN)
    Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.WARN)
    Logger.getLogger("org.apache.kafka.clients.consumer").setLevel(Level.WARN)
    val warehouseLocation = new File("hdfs://cluster/hive/warehouse").getAbsolutePath
    @transient
    val spark = SparkSession
      .builder()
      .appName("Spark SQL To Hive")
      .config("spark.sql.warehouse.dir", warehouseLocation)
      .enableHiveSupport()
      .getOrCreate()
    spark.conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")

    @transient
    val sc = spark.sparkContext
    val scc = new StreamingContext(sc, Seconds(1))
    val kafkaParams = Map[String, Object](
      "auto.offset.reset" -> "latest", //latest,earliest
      "value.deserializer" -> classOf[StringDeserializer]
      , "key.deserializer" -> classOf[StringDeserializer]
      , "bootstrap.servers" -> "10.200.10.24:6667,10.200.10.26:6667,10.200.10.29:6667"
      , "group.id" -> "test_jason"
      , "enable.auto.commit" -> (true: java.lang.Boolean)
    )

    var stream: InputDStream[ConsumerRecord[String, String]] = null
    val topics = Array("test", "test1","test2")

    stream = KafkaUtils.createDirectStream[String, String](
      scc,
      LocationStrategies.PreferConsistent,
      ConsumerStrategies.Subscribe[String, String](topics, kafkaParams)
    )

    stream.foreachRDD(rdd=>{
      if (!rdd.isEmpty()) {
        val cache_rdd = rdd.map(_.value()).cache()
        // a 表
        val a = cache_rdd.filter(_.contains("hello"))
        // b 表
        val b = cache_rdd.filter(_.contains("jason"))
        // 都可以打印结果,下面的代码就不在写了,可以参考另一篇博客里面写hive的
        a.foreach(println)
        b.foreach(println)
      }
    })
    scc.start()
    scc.awaitTermination()
  }
}

代码没有写完整,只要a,b都可以打印出来,下面就和普通的写入hive表没什么区别了,可以参考这个 https://blog.csdn.net/xianpanjia4616/article/details/80958975

这里还有一个思路,可以不用filter,直接写一个完整的schema,然后在下面的sql里面分别查询出a,b表的数据,注册两张临时表,然后写到a,b两个表,这种写法就不在写了,实现起来也比较的简单.

注意:很多人在问,怎么在worker端使用spark创建df,这里说明一下,是不能这么用的,因为spark是在driver端初始化的,而且不能被序列化,所以不能传输到worker上.所以不能在foreach里面使用.

如果有写的不对的地方,欢迎大家指正,如果有什么疑问,可以加QQ群:340297350,更多的Flink和spark的干货可以加入下面的星球

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章