Spark Streaming + kafka

方法一 createStream基于Receiver

  这种方法基于Receiver来接收数据,使用kafka高级自定义API实现。和所有的receivers一样,这种接收方式通过Receiver从kafka接收数据存储到Spark executors节点,然后运行job通过Spark Streaming处理数据
  然而,默认配置下,这种方法在执行失败时会丢失数据(查看Receiver可靠性)。为保证零数据丢失,你必须在SparkStreaming中额外启用Write Ahead Logs,同步地把所有接收到的kafka数据存储到位于分布式系统(e.g HDFS)上的Write Ahead Log里面, 来保证所有的数据在失败后能够恢复,可以在streaming程序指导开发模块中查看更多关于Write Ahead Log的细节

接下来,我们讨论如何使用:

  1. 链接:在使用SBT/Maven项目的scala/java应用程序中引入包

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

  2. 程序:在streaming应用程序代码中,像下面一样导入KafkaUtils和创建一个输入流DStream

    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 中Topic分区和Spark Streaming中RDDS分区没有任何关系,所以在KafkaUtils.createStream() 中增加分区数仅仅只是增加一个Receiver里该topic下消费数据的线程数,而不会增加Spark处理数据的并行数。

    • 能够用不同的group和topic来创建多个Kafka输入流DStream,用多个Receiver并行的接收数据

    • 如果你已经启用Write Ahead Log(e.g HDFS上),接收的数据已经被复制到log中。此后,输入流以StoragelLevel.MEMORY_AND_DISK_SER的优先级来存储

  3. 开发:所有的Spark应用程序中,spark-submit被用来提交运行你的程序。然而,有一些小细节会不同于Scala/Java/Python程序

    在Scala和Java程序中,如果你使用SBT或者Maven来管理项目。确保spark-streaming-kafka_2.10 和它的依赖包,spark-core_2.10 以及 spark-streaming_2.10已经添加到了程序JAR包中。然后可以使用spark-streaming_2.10来运行程序

方法二 creatDirectStream直接访问 (No Receivers)

在Spark1.3中介绍了一种新的不用Receiver的直接访问方法来保证端到端的数据可靠性。不使用Receiver来接收数据,这种方法会定期的查询Kafka上每个topic和partition最近的offsets,根据自定义的offset范围来分批处理数据。当jobs处理程序运行,会调用Kafka的用来读取自定义offset范围的API。这个新特性仅仅在Spark1.3的Scala和Java及以后版本支持。

这个方法相比基于Receiver的方法一有以下优点:

  • 简化并行:不需要创建多个kafka输入流然后union他们。在直接访问方法中,Spark Streaming会创建和Kafka分区一样多的RDD分区,实现并行从Kafka读取数据。在Kafka和RDD分区实现一对一映射,有助于理解和一致性

  • 效率更高:前一种方法中为了防止数据丢失,会请求将数据存储到Write Ahead Log当中,会产生数据复制。实际上,当数据复制两次,一次是Kafka,一次是Write Ahead Log是相当无效率的。第二种方法因为没有Receiver,因此也不需要Write Ahead Logs,解决了这个问题。

  • 一次语义:第一种方法中使用Kafka的高级API来存储在Zookerper里定义的offsets。这种方式在失败后有可能会重复读取数据。这是由于Spark Streaming实际接收的数据和通过Zookeeper追踪的offsets不一致。因此,第二种方法中,我们使用简单的Kafka API而没有使用Zookeeper和offsets追踪,这样消除了Spark Streaming和Zookeeper/Kafka之间的不连续。每条记录,即使是失败后也只能被读取一次。

如何使用:

  1. 链接:这个方法现在仅仅只支持Scala/Java程序。在你的SBT/Maven项目配置文件中,引入如下包

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

  2. 编码:在代码中导入KafkaUtils,创建一个DStream如下

    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 parameters,你需要指定metadata.broker.list 或bootstrap.servers。默认情况下,会从每个Kafka分区最近的offset开始读取,如果你在Kafka parameter中设置 auto.offset.reset=smallest,就会从最小的offset开始读取

    你也可以向KafkaUtils.createDirectStream传入其他参数,来从任意的offset开始读取。而且,如果你想自定义消费的offsets,你可以如下:

    directKafkaStream.foreachRDD { rdd =>
    val offsetRanges = rdd.asInstanceOf[HasOffsetRanges]
    // offsetRanges.length = # of Kafka partitions being consumed

    }

  3. 开发: 和前一种方法一样

更多Spark知识分享请关注我的新blog
https://hywelzhang.github.io/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值