• Spark-Streaming和Kafka集成指南


    Kafka是一个消息发布-订阅系统。Spark-Streaming是spark核心API的扩展,它可以采集Kafka, Flume, Twitter, ZeroMQ, Kinesis, 或TCP sockets等多种数据源进行处理,是一个高可用可伸缩高通量的实时数据计算工具。

    Spark Streaming对接Kafka有两种方式:老方法使用接收器和Kafka的API,新方法(spark1.3以后加入)不使用接收器直接从Kafka接收数据,它们有不同的变成模型、性能特性、语法规则。

    方法1:基于接收器的方式(Receiver-based Approach)

    这种方法使用一个接收器接收数据。接收方使用Kafka高级消费者API实现。通过接收器从Kafka接收到的数据存储在Spark executors中,然后Spark Streaming启动jobs处理数据。然而在默认配置的情况下这种方法可能丢失数据。为了防止数据丢失,必须另外启用Spark Streaming写日志记录,在分布式文件系统(如HDFS)上同步保存所有Kafka接收到的数据记录已便在故障时恢复数据。

    接下来讨论如何在你的spark streaming程序中使用这种方式。

    1.链接:如果使用Maven/SBT开发java/scala项目需要把下面的链接加到streaming项目中:

    1  groupId = org.apache.spark
    2  artifactId = spark-streaming-kafka_2.10
    3  version = 1.6.3

    2.程序设计:在streaming程序代码中,导入kafkaUtils并创建输入流Dstream:

    //java
    
    import org.apache.spark.streaming.kafka.*; JavaPairReceiverInputDStream<String, String> kafkaStream = KafkaUtils.createStream(streamingContext, [ZK quorum], [consumer group id], [per-topic number of Kafka partitions to consume]); //scala import org.apache.spark.streaming.kafka._

    val kafkaStream
    = KafkaUtils.createStream(streamingContext,
    [ZK quorum], [consumer group id], [per
    -topic number of Kafka partitions to consume])

    要记住:

    • Kafka中的主题分区与Spark Streaming中生成的RDD分区不相关。因此,增加主题专用分区KafkaUtils.createStream()的数量仅增加了使用单个接收器内消耗的主题的线程数。它不会增加Spark在处理数据时的并行性。有关更多信息,请参阅主文档。

    • 可以创建多个Kafka输入DStream,具有不同的组和主题,用于使用多个接收器并行接收数据。

    • 如果已使用像HDFS这样的复制文件系统启用了“写入前端日志”,则所接收的数据已被复制到日志中。因此,输入流的存储级别的存储级别StorageLevel.MEMORY_AND_DISK_SER(即使用 KafkaUtils.createStream(..., StorageLevel.MEMORY_AND_DISK_SER))。

    3.部署:和其它spark程序一样,使用spark-submit来提交任务。在scala/java程序中如果使用SBT/Maven创建的项目需要确保spark-streaming-kafka_2.10和你是用的依赖都打在jar包中。

    方法2:直连方式(Direct Approach)

    spark1.3引入了这种直连的方式,确保更强的端到端的保证。这种方式不使用接收器,而是定期查询Kafka在每个topic+partition中的最新偏移量,并相应的定义在每个批处理中要处理的偏移范围。当处理数据的任务被启动时,kafka消费者API就去读取kafka定义的偏移范围。

    这种方法比基于接收器的方法具有以下优点(即方法1)

    • 简化并行度:无需创建多个输入kafka stream并联合它们。随着directStream,Spark Streaming将创建尽可能多的RDD分区,因为有Kafka分区要消耗,这将分别从Kafka读取数据并行。所以在Kafka和RDD分区之间存在一对一的映射,这更容易理解和调整。

    • 效率:在第一种方法中实现零数据丢失需要将数据存储在写入前端日志中,进一步复制数据。这实际上是低效的,因为数据有效地被复制了两次 - 一次是由卡夫卡(Kafka),另一次是通过写入前端日志。第二种方法消除了问题,因为没有接收器,因此不需要写入前端日志。只要您有足够的卡夫卡保留,可以从卡夫卡恢复邮件。

    • 完全一次的语义:第一种方法使用Kafka的高级API在Zookeeper中存储消耗的偏移量。这通常是从卡夫卡消费数据的方式。虽然这种方法(结合写入日志)可以确保零数据丢失(即至少一次语义),但是在某些故障下,一些记录可能会被消耗两次的可能性很小。这是因为Spark Streaming可靠接收的数据与Zookeeper跟踪的偏移量之间的不一致。因此,在第二种方法中,我们使用不使用Zookeeper的简单Kafka API。Spark Streaming在其检查点内跟踪偏移量。这消除了Spark Streaming和Zookeeper / Kafka之间的不一致,因此,尽管出现故障,每个记录都有效地被Spark Streaming收到。

    请注意,这种方法的一个缺点是它不会在Zookeeper中更新偏移量,因此基于Zookeeper的Kafka监视工具将不会显示进度。但是,您可以在每个批次中访问此方法处理的偏移量,并自己更新Zookeeper。

    1.链接:仅在Scala / Java应用程序中支持此方法。将SBT / Maven项目与以下工件链接

     groupId = org.apache.spark
     artifactId = spark-streaming-kafka_2.10
     version = 1.6.3

    2.编程:在streaming程序代码中,导入KafkaUtils并创建输入流DStream,如下所示:

    //java
    
     import org.apache.spark.streaming.kafka.*;
    
     JavaPairReceiverInputDStream<String, String> directKafkaStream = KafkaUtils.createDirectStream(streamingContext,
             [key class], [value class], [key decoder class], [value decoder class],
             [map of Kafka parameters], [set of topics to consume]);
    
    //scala
    
     import org.apache.spark.streaming.kafka._
    
     val directKafkaStream = KafkaUtils.createDirectStream[
         [key class], [value class], [key decoder class], [value decoder class] ](
         streamingContext, [map of Kafka parameters], [set of topics to consume])

    在Kafka参数中,必须指定metadata.broker.list或者bootstrap.servers。默认情况下,它将从每个Kafka分区的最新偏移开始消耗。如果将auto.offset.resetKafka参数中的配置设置为smallest,那么它将从最小的偏移量开始消耗。

    3.部署:和方法1相同。

  • 相关阅读:
    spring总结
    mybatis总结
    HttpClient,okhttp,Jodd-http 使用上的差异
    RPC序列化
    RPC是什么? (学习笔记)
    MySQL普通索引与唯一索引
    MySQL 存储引擎
    TCP的流量控制和拥塞控制
    【转载】Windows自带.NET Framework版本大全
    [知识点] 总目录
  • 原文地址:https://www.cnblogs.com/fuos/p/7274650.html
Copyright © 2020-2023  润新知