Spark Streaming揭秘 Day15 No Receivers方式思考

Spark Streaming揭秘 Day15

No Receivers方式思考

在前面也有比较多的篇幅介绍了Receiver在SparkStreaming中的应用,但是我们也会发现,传统的Receiver虽然使用比较方便,但是还是存在不少问题的,今天主要围绕kafka direct access讨论下,如果抛开Receiver来实现inputDStream该怎么做。

KafkaRDD

我们知道,在Spark中,数据的访问主要是通过RDD来进行,而针对Kafka的数据,是使用了KafkaRDD。

让我们进入KafkaRDD的定义,可以看到主要和数据访问相关的是一个包含OffsetRange的数组。
Snip20160527_22
Snip20160527_23

OffsetRange是对offset的范围定义,offset是什么?我们可以理解它是kafka中类似指针、游标的概念,一个offset代表了一个消息。

如果来使用这个OffsetRange,和其他RDD一样,主要是通过getPartition和compute两个方法。

getPartition主要是进行数据定位,里面对每个OffsetRange进行遍历,首先是获取了Kafka的地址,第二步是根据OffsetRange创建了一个KafkaRDDPartition。其中i是zipWithIndex方法生成的分区索引。
Snip20160527_24

compute方法中,将不同的topic的partition对应生成KafkaRDD的partition,会根据KafkaRDDPartition提取出我们需要的内容,主要是会用到KafkaRDDIterator这个方法。从这段代码,我们可以看出KafkaRDDIterator是真正获取数据的方法,是lazy级别的方法,和KafkaRDDPartition一一对应。
Snip20160527_25

KafkaRDDIterator是一个内部类,封装了对Kafka进行编程的逻辑。其代码逻辑主要是针对kafkaAPI的调用,采用的是SimpleConsumer这个数据模型,这个就不再详细深入。
Snip20160527_26

DirectKafkaInputDStream

讲完了RDD,我们来看一下对于inputDStream的应用。

首先看下创建inputDStream的代码:

Snip20160527_27

createDirectStream,可以直接指定range,如果不指定range的话,会根据参数设置进行获取,smallest是拿最早的数据,否则拿最晚的数据。最终是返回一个DirectKafkaInputDStream。

Snip20160527_28

在DirectKafkaInputDStream中,主要是通过compute方法产生RDD实例,KafkaRDD和inputDStream一一对应。
Snip20160527_33

有两点需要注意:

计算重试一次,主要是为了确保语义一致性。
Snip20160527_29

在读取数据过程中,可以通过rateController控制消费数据的速度,并且这个速度可以为每个partition单独进行配置!!!
Snip20160527_32

小结

Direct方式对我们实际的价值:
1.Direct方式没有缓存,不会出现内存溢出。
2.Receiver默认和executor绑定,Direct默认数据在多个executor上,会更方便做分布式。
3.数据消费问题,如果采用receiver方式,如果数据来不及处理,Delay多次的话,SparkStreaming可能会崩溃,Direct方式不会有这种情况,delay只是不进行下一个处理,无所谓。
4.完全的语义一致性,不会重复消费数据,并且能消费数据一定被消费,因为直接和kafka交互,只是真正执行成功之后,才会被记录下来。
5.Direct方式因为不需要内存管理,比Receiver方式性能高。

欲知后事如何,且听下回分解

DT大数据每天晚上20:00YY频道现场授课频道68917580

原文地址:https://www.cnblogs.com/dt-zhw/p/5534434.html