Spark Streaming消费Kafka Avro数据

场景

上游数据同步mysql的binlog数据并推到kafka,我们作为下游需要将数据接过来,进行处理,之后存入对外提供服务的数据库中。

方案

使用Spark Streaming消费kafka实现近实时的效果,使用kafka低级api direct的方式,来接收数据

direct 方式会周期性地查询Kafka,来获得每个topic+partition的最新的offset,从而定义每个batch的offset的范围。当开始处理数据时,会获取指定offset范围的数据,当前批数据完全处理完成之后,再将offset提交,可以保证至少一次的特性。

如果数据丢在kafka自身的环节,由于每个topic是有副本的,可以通过副本机制找回。

如果是消费程序挂掉导致的数据缺失,由于上次的偏移量范围对应的batch没有处理成功,再次重启程序的时候,只会从上次成功的offset出开始消费,以此实现至少一次的语义。

code

val topic = tables.map("bb_" + _).toSet[String]
//获得sparkContext对象
val sc = SparkConfig.getSparkSession(s"kafka-streaming").sparkContext
//创建streamingContext
val ssc = new StreamingContext(sc,Milliseconds(millSeconds))

//kafka 配置
val kafkaParams = Map[String,Object](
    "bootstrap.servers" -> "xxxx:9092,xxxx:9092,xxxx:9092",
    "group.id" -> "xxxx",
    "auto.offset.reset" -> "earliest",
    //上游数据是avro格式的,配置avro schema registry解析arvo数据
    "schema.registry.url" -> "http://192.168.100.182:8081",
    "key.deserializer" -> classOf[StringDeserializer],
    //值是avro数据,需要通过KafkaAvroDeserializer反序列化
    "value.deserializer" -> classOf[KafkaAvroDeserializer],
    //自己来决定什么时候提交offset
    "enable.auto.commit" -> (false: java.lang.Boolean)
)

//使用的kafka010版本的api
val kafkaStream = KafkaUtils.createDirectStream[String,Object](
    ssc,
    //持久化策略
    PreferConsistent,
    //订阅信息
    Subscribe[String,Object](topic, kafkaParams)
)

//处理每个微批的rdd
kafkaStream.foreachRDD( rdd => {
    if(rdd!=null && !rdd.isEmpty()){
        //获取偏移量
        val offsetRange = rdd.asInstanceOf[HasOffsetRanges].offsetRanges
        //对每个分区分别处理
        rdd.foreachPartition( iterator  => {
            if( iterator != null && !iterator.isEmpty ){
                 //作相应的处理
            	 while (iterator.hasNext) {
                     //处理每一条记录
                     val next = iterator.next
                     //这个就是接收到的数据值对象,
                     val record = next.value().asInstanceOf[Record]
                 	//可以插入数据库,或者输出到别的地方
                     ...
                 }
            }
        })
        //将偏移量提交(偏移量是提交到kafka管理的)
        kafkaStream.asInstanceOf[CanCommitOffsets].commitAsync(offsetRange)
        println("submit offset!")
    }
})

ssc.start()
ssc.awaitTermination()

pom

列出了反序列化avro和sparkstreaming结合kafka010的依赖,备忘


    io.confluent
    kafka-avro-serializer
    3.0.0



    org.apache.spark
    spark-streaming-kafka-0-10_2.11
    2.3.1

相关链接

spark官方文档: http://spark.apache.org/docs/latest/streaming-kafka-0-10-integration.html

sparkstreaming kafka demo: https://dongkelun.com/2018/06/20/sparkStreamingOffsetOnlyOnce/

kafka 08和010概述: https://blog.csdn.net/weixin_43228814/article/details/88889894

spark消费kafka两种方式的区别: https://blog.csdn.net/qq_41571900/article/details/84205181


简单的应用层面,如果有不对的地方欢迎指正。

你可能感兴趣的:(Spark,Spark,Streaming,Kafka,Avro)