SparkStreaming实时流式大数据处理实战总结

总结《SparkStreaming实时流式大数据处理实战》

一、初始spark

1. 初始sparkstreaming

1.1 大数据处理模式

1. 一种是原生流处理(Native)的方式,即所有输入记录会一条接一条地被处理,storm 和 flink

2. 另一种是微批处理(Batch)的方式,将输入的数据以某一时间间隔,切分成多个微批量数据,然后对每个批量进行处理,sparkStreaming

 

1.2 消息传输保障

at most once  至多一次,可能会丢

at least once  至少一次,可能重复

exactly once  精确传递一次

 

1.3 容错机制

流式处理发生中断出错的现象是常有的情况,可能是发生在网络部分、某个节点宕机或程序异常等。,当发生错误导致任务中断后,应该能够恢复到之前成功的状态重新消费。

 

Storm是利用记录确认机制(Record ACKs)来提供容错功能。

Spark Streaming则采用了基RDD Checkpoint的方式进行容错。

 

1.4 性能

延时时间:storm > spark

吞吐量 :spark > storm

 

1.5. Structed Streaming(结构化)简述

不同点:

Spark Streaming是以RDD构成的DStream为处理结构.

Structed Streaming是一种基于Spark SQL引擎的可扩展且容错的流处理引擎

Structed 提供了更加低延迟的处理模式

 

相同点:

都是微批的实时处理,内部并不是逐条处理数据记录,而是按照一个个小batch来处理,从而实现低延迟的端到端延迟和一次性容错保证。

 

二、共享变量

节点之间会给每个节点传递一个map、reduce等操作函数的独立副本,这些变量也会被复制到每台机器上,而节点之间的运算是相互独立的。

这些变量会被复制到每一台机器上,并且当变量发生改变时,并不会同步传播回Driver程序。

如果进行通用支持,任务间的读写共享变量需要大量的同步操作,这会导致低效。

Spark提供了两种受限类型的共享变量用于两种常见的使用模式:广播变量累加器

 

2.1 累加器(Accumulator)

累加器是一种只能通过关联操作进行“加”操作的变量,因此它能够高效地应用于并行操作中。累加器能够用来实现对数据的统计和求和操作。Spark原生支持数值类型的累加器,开发者可以自己添加支持的类型。

 

 

节点上的任务可以利用add方法进行累加操作,但是它们并不能读取累加器的值。只有Driver程序能够通过value方法读取累加器的值。

 

2.2 广播变量(Broadcast)

广播变量允许程序员在每台机器上缓存一个只读的变量,而不是每个任务保存一份拷贝。

利用广播变量,我们有效的将一个大数据量输入集合的副本分配给每个节点。Spark也有效的利用广播算法去分配广播变量,以减少通信的成本。

 

 

 

可以利用广播变量将一些经常访问的大变量进行广播,而不是每个任务保存一份,这样可以减少资源上的浪费。

 

 

三、DStream

Spark Streaming对微批处理方式做了一个更高层的抽象,将原始的连续的数据流抽象后得到的多个批处理数据(batches)抽象为离散数据流(discretized stream),DStream本质是RDD数据结构的序列

 

3.1 DStream的创建方式

一是从Kafka、Flume等输入数据流上直接创建。

二是对其他DStream采用高阶API操作之后得到(如map、flatMap等)。

 

3.2 DStream的Transform操作

与RDD的Transformation类似,DStream的转移操作也不会触发真正的计算,只会记录整个计算流程。

  • map
  • flatMap
  • fliter
  • repartition
  • union
  • reduce
  • join

 

3.2.1 UpdateStateByKey操作

流式处理本身是无状态的,如何记录更新一种状态呢?

我们可以利用外部存储介质或者利用累加器来实现,而UpdateStateByKey就是专门用于这项工作,可以利用这个操作根据新的信息流持续地更新任意状态。

(1)定义状态(state):该状态可以是任意数据类型。

(2)定义状态更新函数(update function):我们需要制定一个函数,根据先前的状态和数据流中新的数据值来更新状态值。

 

特别注意:使用updateStateByKey需要配置checkpoint,这个将在后面详细介绍。

 

3.2.2 Transform操作

 

 

 传入的函数会在每个时间间隔(interval)的batch中被执行,这允许我们做不同时间段的RDD操作,也就是说RDD操作、分支(partitions)数量及广播变量等都可在batch间进行改变。

 

3.2.3 windows操作

Spark Streaming还提供了基于窗口的计算,允许我们在滑动窗口数据上进行Transformation操作。

 

 

在原始DStream上,窗口每滑动一次,在窗口范围内的RDDs就会结合、操作,形成一个新的基于窗口的DStream(windowed DStream)。

  •  窗口长度(window length):窗口的持续时长(图中为3)。
  • 滑动间隔(sliding interval):执行窗口操作的时间间隔(图中为2)。

 

 

3.2.4. join操作

(1)Stream-Stream join操作

 

 

 

 

(2)Stream-dataset join操作

 

 

 

这里的dataset是RDD数据类型,在前面介绍Transform时我们提到DStream的Transform操作使我们能够直接操作DStream内部的RDD,所以可以利用上述操作将二者拼接起来。

 

3.3 DStream 的输出操作

将DStream中的数据保存到外部系统中,如数据库或者文件系统。与RDD中的Action操作类似,DStream中只有输出操作才会触发DStream的转移操作(Transformation)。

  • print()
  • saveAsObjectFiles(prefix,[suffix])
  • saveAsTextFiles(prefix.[suffix])
  • foreachRDD(func) 会将传入的func函数应用在DSteam中的每个RDD上,值得注意的是func函数通常会运行在Driver中,并且由于Spark是惰性的,func需要包含Action操作,以此推动整个RDDs的运算。

在实际生产环境中,foreach()这个操作是常用到的,我们可以利用该函数将DStream中的数据按照需要的方式,输出到指定外部系统中,如MySQL、Redis、HBase、文件等

 

3.4 SparkStreaming初始化及输入源

3.4.1初始化流式上下文(StreamingContext)

初始化sparkStreaming需要sparkContext 

 

 在创建了上下文对象之后,还需要进一步创建输入DStream来指定输入数据源,下面具体介绍。

 

3.4.2 输入源及接收器(Receivers)

创建输入源:

  1. 基本数据源,这类数据源可以直接由StreamingContext API使用,如文件系统或者套接字连接(socket connections)。
  2. 高级数据源:像Kafka、Flume、Kinesis等数据源,需要使用额外的接口类。

 

3.4.2.1 基本数据流

  1. Socket文本数据流:通过TCP套接字连接接收文本数据产生DStream。
  2. File数据流:从文件或者任何兼容的文件系统(HDFS、S3、NFS等)中读取数据产生DStream。
  3. RDDs队列(queue)作为数据流:在测试Spark Streaming应用时,可以将一系列RDD,使用streamingContext.queueStream(queueofRDDs)来产生DStream,每个进入队列的RDD,会被认为是DStream中的一批(batch)数据,会以流式的方式进行处理。

 

3.4.3持久化、Checkpointing和共享变量

3.4.3.1 DStream持久化(caching/presistence)

对于基于窗口的操作如reduceByWindow和reduceByKeyAndWindow,以及基于状态的操作如updateStateByKey,它们本身就暗含了对同一数据进行多重操作的特性。因此,由基于窗口操作产生的DStream,即使开发者不主动调用persist()方法,DStreams也会自动持久化在内存当中。默认是内存。

 

3.4.3.2 Checkpointing操作

一般来说,一个流式处理程序需要24小时不间断运作,所以其必须拥有一定的与程序逻辑本身相独立的容错机制(如系统错误、虚拟机宕机等)。Spark Streaming的容错恢复系统必须拥有检查点(checkpoint)的充足信息,从而能够从失败中恢复过来。其中主要有两种类型的数据被检查点记录下来。

 

第一种,元数据检查点(metadata checkpointing):保存流式计算中用于容错存储的信息,如HDFS。这些信息会被用来恢复driver节点的流式应用。

  • 配置(Configuration):用于创建流式应用的配置信息。
  • DStream操作:流式应用中定义的DStream操作集。
  • 未完成的批处理(batches):工作(Job)已经入队但是还未完成的批处理。

 

第二种,数据检查点(data checkpointing):将已经生成的RDDs进行可靠的存储。这在一些依赖于多个batch数据的状态转移操作(stateful transformation)中是必须的。

transform 状态转移操作的中间RDD会通过定期检查点(checpoint)输出到可靠的存储介质当中(如HDFS),从而切断这种依赖链的影响。

 

下面的条件,则必须使用检查点(checpointing):

  1. 使用有状态转移操作(stateful transformation):如果在应用中使用了updateStateByKey或者类似reduceByKeyAndWindow的操作,则必须设置检查点目录(checkpoint directory),从而能够定期保存RDD。
  2. 将运行程序的Driver节点从失败中恢复:元数据检查点被用来恢复这个过程。

检查点的保存目录可以设置为(如HDFS、S3等),这样检查点的信息就会保存在我们所设置的目录下,我们可以使用streamingContext.checkpoint(checkpoint Directory)进行设置。

 

当程序第一次运行时,其必须创建新的StreamingContext,并且设定好所有的流(streams),之后调用start()函数。

当一个程序需要从失败中重启时,其会根据检查点目录中保存的检查点数据来重建StreamingContext。

 

 

 

RDD检查点保存到可靠存储空间中时,会有一定的消耗。这可能会使得那些被保存RDD检查点的batches的处理时间加长,因此检查点的间隔(interval)需要谨慎设置。在最小的batch尺度上(1s),每个batch的检查点设置可能会严重降低操作的生产量。而相反,如果检查点过于频繁,会导致任务尺寸的增长,造成不利的影响。

通常在DStream间隔(intervals)的基础上增加5~10s是一个比较好的检查点时间间隔。

 

特别说明,关于累加器、广播变量的检查点会有所不同,累加器和广播变量无法从Spark Streaming的检查点恢复。

 

如果我们开启了检查点(checpointing),并且同时使用了累加器或者广播变量,那么必须为累加器和广播变量创建一个惰性实例化的单例(lazily instantiatedsingleton instances),从而使得它们能够在Driver重启时能够再次被实例化,代码如下:

 

 

 

 

posted @ 2021-01-29 20:12  彬在俊  阅读(1367)  评论(0编辑  收藏  举报