SparkStreaming 从 Kafka中接收数据的两种方式与调优

一、Receiver方式

1.调用高阶API;
2.通过Receiver接收器来读取数据,被动接收数据;
3.接收到的数据在executor内存中;
4.Spark的分区和Kafka分区不相关,加大topic分区无法提高spark并行度;
5.数据可能丢失。1.2以后通过checkpoint和配置spark.streaming.receiver.writeAheadLog.enable防止数据丢失;
6.通过MEMORY_AND_DISK_SER提高数据吞吐量;
7.zookeeper维护offset;
8.仍然有问题,数据处理效率、资源浪费、spark计算延迟、程序失败再恢复可能会数据重复计算。
9.使用:

KafkaUtils.createStream
a)调用该函数时会创建一个继承于 ReceiverInputDStream的KafkaInputDStream对象;
b)KafkaInputDStream对象会调用getReceiver 来获取接收对象的receiver;
c)recever 会在 executor 上启动,接收并发送数据到ReceiverSupervisor;
d)ReceiverSupervisor 将数据存为 block 作为 RDD 输入数据
SparkStreaming 从 Kafka中接收数据的两种方式与调优_第1张图片

二、Direct 方式

1.调用低阶API;
2…Spark的分区和Kafka分区一一对应;
3.数据零丢失;
4.任务触发,executor主动去kafka读取数据;
5.driver决定读取的offset,由checkpoint维护,不会更新zookeeper的offset,可自行更新。
6.使用:

KafkaUtils.createDirectStream

a)调用时创建DirectKafkaInputDStream对象;
b)DirectKafkaInputDStream对象调用compute方法;
c)在compute方法中:
①计算各主题各分区的最大偏移量,来确定拉取分区中的哪一块数据;
②创建kafkaRDD对象,并执行count操作,获取各个分区内指定的offsetRange数据;
③生成inputinfo(streamID、offset等),添加到JobScheduler
④返回待遇数据的rdd。

注:在kafkaRDD中有getPartitions方法,这个方法可以保证kafka分区与rdd的分区一致。

三、使用场景

Direct 方式:应用程序第一次启动,还未消费Kafka数据,此时从largest处读取数;

Receiver方式:应用程序进行重启,需要保证从上次的offsets处开始读取数据。

四、调优

1、批处理时间:太小导致作业频繁提交,太大导致积攒数据量大;
2、kafka数据拉取量:默认全部拉出,通过spark.streaming.kafka.maxRatePerPartition设置;
3、JVM GC:建议:–conf “spark.executor.extraJavaOptions=-XX:+UseConcMarkSweepGC”;
4、CPU资源数:core和momory;
5、partition和parallelism的数量:每个Task只能处理一个partition的数据,太小导致每个切片数据量大,内存压力大,太大导致切片多,影响效率,parallelism指进行shuffle时返回的分区数,通过spark.default.parallelism设置;
6、高性能算子:
reduceByKey/aggregateByKey替代groupByKey
mapPartitions替代普通map
foreachPartitions替代foreach
repartitionAndSortWithinPartitions替代repartition与sort
filter之后进行coalesce操作
7、重复使用的Dstream:对rdd进行cache()操作;
8、Kryo优化序列化性能 : conf.set(“spark.serializer”, “org.apache.spark.serializer.KryoSerializer”)

你可能感兴趣的:(spark)