文章目录

1.什么是 Spark Streaming

Spark Streaming 是一个基于 Spark Core 之上的实时计算框架,可以从很多数据源消费数据并对数据进行实时的处理,具有高吞吐量和容错能力强等特点。

Spark Streaming_面试题_数据
kafka关系型数据,Flume日志半关系型数据,HDFS数据 => hdfs, 数据库, 数据展示台

2.Spark Streaming 如何执行流式计算的?

Spark Streaming 中的流式计算其实并不是真正的流计算,而是微批计算。Spark Streaming 的 RDD 实际是一组小批次的 RDD 集合,是微批(Micro-Batch)的模型,以批为核心。

Spark Streaming 在流计算实际上是分解成一段一段较小的批处理数据(Discretized Stream),其中批处理引擎使用 Spark Core,每一段数据都会被转换成弹性分布式数据集 RDD,然后 Spark Streaming 将对 DStream 的转换操作变为 Spark 对 RDD 的转换操作,并将转换的中间结果存入内存中,整个流式计算依据业务的需要可以对中间数据进行叠

3.WordCount

object Spark01 {
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf().setAppName("Streaming").setMaster("local[*]")
val ssc = new StreamingContext(sparkConf, Seconds(3))

val inputStream = ssc.socketTextStream("localhost", 9999)
val dataStream = inputStream.flatMap(_.split(" "))
.map((_, 1))
.reduceByKey(_+_)
dataStream.print()

// 启动采集器
ssc.start()
// 等待采集器关闭
ssc.awaitTermination()
}

}

4. Spark Streaming 常用算子

Transformations:
map、flatMap、filter、union、reduceByKey、join、transform,这是算子都是无状态转换,当前批次的处理不需要使用之前批次的数据或中间结果。

action:
print、saveAsTextFile、saveAsObjectFiles、saveAsHadoopFiles等。

5.有状态转换算子

基于追踪状态变化的转换(updateStateByKey)
updateStateByKey:将历史结果应用到当前批次。

滑动窗口的转换 Window Operations

6.Spark Streaming 如何实现精确一次消费

精确一次消费(Exactly-once) 是指消息一定会被处理且只会被处理一次。不多不少就一次处理。

至少一次消费(at least once),主要是保证数据不会丢失,但有可能存在数据重复问题。

最多一次消费 (at most once),主要是保证数据不会重复,但有可能存在数据丢失问题。

方案一:利用关系型数据库的事务进行处理

出现丢失或者重复的问题,核心就是偏移量的提交与数据的保存,不是原子性的。如果能做成要么数据保存和偏移量都成功,要么两个失败。那么就不会出现丢失或者重复了。

这样的话可以把存数据和偏移量放到一个事务里。这样就做到前面的成功,如果后面做失败了,就回滚前面那么就达成了原子性。

方案二:手动提交偏移量+幂等性处理

首先解决数据丢失问题,办法就是要等数据保存成功后再提交偏移量,所以就必须手工来控制偏移量的提交时机。

但是如果数据保存了,没等偏移量提交进程挂了,数据会被重复消费。怎么办?那就要把数据的保存做成幂等性保存。即同一批数据反复保存多次,数据不会翻倍,保存一次和保存一百次的效果是一样的。如果能做到这个,就达到了幂等性保存,就不用担心数据会重复了。

在实际的开发中手动提交偏移量其实不难,难的是幂等性的保存,有的时候并不一定能保证。所以有的时候只能优先保证的数据不丢失。数据重复难以避免。即只保证了至少一次消费的语义。

7. 背压机制

在默认情况下,Spark Streaming 通过 receivers (或者是 Direct 方式) 以生产者生产数据的速率接收数据。当 batch processing time > batch interval 的时候,也就是每个批次数据处理的时间要比 Spark Streaming 批处理间隔时间长;越来越多的数据被接收,但是数据的处理速度没有跟上,导致系统开始出现数据堆积,可能进一步导致 Executor 端出现 OOM 问题而出现失败的情况。

背压机制:

设置 spark.streaming.backpressure.enabled:ture;开启背压机制后 Spark Streaming 会根据延迟动态去 kafka 消费数据;

上限由 spark.streaming.kafka.maxRatePerPartition 参数控制,所以两个参数一般会一起使用。

8.SparkStreaming 有哪几种方式消费 Kafka 中的数据

一、基于 Receiver 的方式
receiver 从 Kafka 中获取的数据都是存储在 Spark Executor 的内存中的,这种方式可能会因为底层的失败而丢失数据

二、基于 Direct 的方式
这种方式会周期性地查询 Kafka,来获得每个 topic+partition 的最新的 offset,从而定义每个 batch 的 offset 的范围。

在实际生产环境中大都用 Direct 方式

因为,基于 receiver 的方式,是使用 Kafka 的高阶 API 来在 ZooKeeper 中保存消费过的 offset 的。这是消费 Kafka 数据的传统方式。这种方式配合着 WAL 机制可以保证数据零丢失的高可靠性,但是却无法保证数据被处理一次且仅一次,可能会处理两次。因为 Spark 和 ZooKeeper 之间可能是不同步的。

基于 direct 的方式,使用 kafka 的简单 api,Spark Streaming 自己就负责追踪消费的 offset,并保存在 checkpoint 中。Spark 自己一定是同步的,因此可以保证数据是消费一次且仅消费一次。