【Spark】spark streaming

一、简介

Spark Streaming是一种准实时的流式计算框架,它对数据处理的单位是一批而不是一条,在数累积到设置的时间间隔后,对数据进行统一的微批处理。这个时间间隔是Spark Streaming的核心概念和关键参数,直接决定了Spark Streaming作业的数据处理延迟,当然也决定了吞吐量和性能。实时数据的来源可以是:Kafka, Flume, Twitter, ZeroMQ或者TCP sockets,并且可以使用高级功能的复杂算子来处理流数据。例如:map,reduce,join,window 。最终,处理后的数据可以存放在文件系统,数据库等,方便实时展现。

【Spark】spark streaming_第1张图片

二、底层原理

Spark Streaming中基本的抽象是离散流(DStream),DStream代表的是一个连续的数据流,它的底层实际上是由一系列连续的RDD组成的。每个RDD包含确定时间间隔内的数据,这些离散的RDD连在一起,组成了对应的DStream。所以对DStream的操作,实际上都转化成了对一系列的RDD操作。想要学好Spark Streaming,不妨先把Spark最底层的RDD弄明白。

三、执行流程

【Spark】spark streaming_第2张图片

1、我们在集群中的其中一台机器上提交我们的Application Jar,然后就会产生一个Application,开启一个Driver,然后初始化SparkStreaming的程序入口StreamingContext;

2、Master会为这个Application的运行分配资源,在集群中的一台或者多台Worker上面开启Excuter,executer会向Driver注册;

3、Driver服务器会发送多个receiver给开启的excuter,(receiver是一个接收器,是用来接收消息指定位置传来的消息,在excuter里面运行的时候,其实就相当于一个task任务)

4、receiver接收到数据后,默认每隔200ms就生成一个block块,就是一个rdd的分区,然后这些block块就存储在executer里面

5、receiver产生了这些block块后会把这些block块的信息发送给StreamingContext;

6、StreamingContext接收到这些数据后,会根据一定的规则将这些产生的block块定义成一个rdd,然后将rdd封装成了DStream

7、Spream Streaming的一系列逻辑操作都是在DStream上,最后返回结果

注意以下:

1.所有的代码逻辑完成后要有一个output operation触发类算子 比如:DStream.print();

2. Streaming框架启动后需要手动调用方法,启动后不能再次添加业务逻辑 JavaStreamingContext.start();

3.//等待spark程序被终止 JavaStreamingContext.awaitTermination();

4.JavaStreamingContext.stop() 无参的stop方法将SparkContext一同关闭,等同于stop(true) 但是stop(false),不会关闭SparkContext。

5.JavaStreamingContext停止之后不能再调用start

四、几种算子

1.transformation算子

1)transform:可以通过transform算子,对Dstream做RDD到RDD的任意操作

2)updateStateByKey:

①为SparkStreaming中每一个Key维护一份state状态,state类型可以是任意类型的,可以是一个自定义的对象,更新函数也可以是自定义的。

②通过更新函数对该key的状态不断更新,对于每个新的batch而言,SparkStreaming会在使用updateStateByKey的时候为已经存在的key进行state的状态更新。

注意:使用到updateStateByKey要开启checkpoint机制和功能,并且持久化按照如下规则:如果batchInterval设置的时间小于10秒,那么10秒写入磁盘一份。如果batchInterval设置的时间大于10秒,那么就会batchInterval时间间隔写入磁盘一份

用途:统计广告点击流量,统计这一天的车流量,统计点击量

3)reduceByKeyAndWindow:

比如说计算每隔20秒,计算最近30秒内的数据,那么窗口的大小就是30秒,滑动时间间隔是20秒。

注意:

①滑动时间间隔和窗口大小必须是batchInterval的整数倍

②比如上面的例子,可以进行优化操作,优化后的window操作要保存状态所以要设置checkpoint路径,没有优化的window操作可以不设置checkpoint路径

2.output operation算子

1) foreachRDD

必须对抽取出来的RDD执行action类算子,代码才能执行。

2)print

打印DStream的当前数据

3)saveAsTextFiles

将数据存到本地的文件目录下

4)saveAsHadoopFiles

将数据保存到hdfs上

四、HA(Driver)

第一:提交任务层面,在提交任务的时候加上选项 --supervise,当Driver挂掉的时候会自动重启Driver。

第二:代码层面,使用JavaStreamingContext.getOrCreate(checkpoint路径,JavaStreamingContextFactory

五、SparkStreaming整合Kafka

1.receiver模式

【Spark】spark streaming_第3张图片

执行流程:

①SparkStreaming的Executor接收到Kafka传来的数据

②会对数据进行备份到其他的executor上,默认持久化级别是MEMORY_AND_DISK_SER_2

③备份完成后去zookeeper中更新消费偏移量

④向Driver端的receiver Tracker汇报备份数据的位置信息

⑤Driver把task任务分发到Executor上执行并返回执行情况和结果

存在的问题:

①数据丢失问题

当备份完成后向zookeeper中更新偏移量之后,Driver宕机,会导致executor也挂掉,就会存在数据找不到的问题

解决方案:开启WAL机制。在备份数据的时候也同时将数据备份到hdfs上面,同时需要将持久化级别降级到MEMORY_AND_DISK,但是这样做会导致延迟较高

②重复消费问题

当开启WAL机制之后,如果在备份完成之后,提交偏移量到zookeeper之前,Driver挂掉,下次重启之后就会先去消费hdfs上存在的数据,但是这部分的偏移量还没有提交到zookeeper,就还会在被消费一次

解决方案:用driect模式

并行度:

batchInterval/blockInterval

blockInterval来决定的,默认为200ms,假设batchInterval为5s,那么每隔blockInterval就会产生一个block,这里就对应每批次产生RDD的partition,这样5秒产生的这个Dstream中的这个RDD的partition为25个,并行度就是25。

2.driect模式

Driect模式与Receiver模式的最大区别就是偏移量不再提交到zookeeper上,而是由executor自己管理。数据也不再是由kafka发送,是自己去kafka上拉取数据。

并行度:

kafka中topic的partition数决定的。

六、反压机制

默认情况下,Spark Streaming通过receiver以生产者生产数据的速率接收数据,计算过程中会出现批处理时间大于批间隔时间的情况,其中批处理时间为实际计算一个批次花费的时间,批间隔时间是为Streaming设置的批处理时间。这种情况就有可能会造成数据堆积,导致receiver所在的executor内存溢出问题。

通过设置spark.streaming.backpressure.enabled=true(默认false)来开启动态反压机制,根据JobScheduler反馈作业的执行信息来动态调整数据接受速率。当然,启用反压机制也会占用一定的内存资源。

七、相关配置

预写日志:spark.streaming.receiver.writeAheadLog.enable默认false没有开启

blockInterval:spark.streaming.blockInterval默认200ms

Receiver模式接收速率:spark.streaming.receiver.maxRate默认没有设置

Direct模式接受速率:spark.streaming.kafka.maxRatePerPartition默认没有设置

优雅的停止sparkstream :

spark.streaming.stopGracefullyOnShutdown 设置成true

然后用命令kill -15/sigterm driverpid

你可能感兴趣的:(大数据,Spark)