大数据常见面试题之Spark Streaming

一.SparkStreaming有哪几种方式消费kafka中的数据,他们之间的区别是什么?

1.基于Receiver的方式

  • 这种方式使用Receiver来获取数据.Receiver是使用kafka的高层次Consumer API来实现的.reveiver从kafka中获取的数据都是存储在spark executor的内存中的(如果突然数据暴增,大量batch堆积,很容易出现内存溢出的问题),然后spark streaming启动的job会去处理哪些数据
  • 然而,在默认的配置下,这种方式可能会因为底层的失败而丢失数据,如果要启用高可用机制,让数据零丢失,就必须启用spark streaming的预写日志机制(Write Ahead Log,WAL).该机制会同步地将接收到的kafka数据写入分布式文件系统(比如hdfs)上的预写日志中.所以,即使底层节点出现了失败,也可以使用预写日志中的数据进行恢复

2.基于Direct的方式

  • 这种不基于Receiver的直接方式,是在spark1.3中引入的,从而能够确保更加健壮的机制.替代掉使用Receiver来接收数据后,这种方式会周期性地查询kafka,来获得每个topic+partition的最新的offset,从而定义每个batch的offset的范围.当处理数据的job启动时,就会使用kafka的简单consumer api来获取kafka指定offset范围的数据

优点如下:

  • 简化并行读取:如果要读取多个partition,不需要创建多个输入DStream然后对他们进行union操作.Spark会创建跟 kafka partition 一样多的RDD partition.并且会并行从kafka中读取数据.所以在kafka partition 和RDD partition之间,有一个一对一的映射关系
  • 高性能:如果要保证零数据丢失,在基于receiver的方式中,需要开启WAL机制.这种方式其实效率低下,因为数据实际上被复制了两份,kafka自己本身就有高可靠机制,会对数据复制一份,而这里又会复制一份到WAL中.而基于direct的方式,不依赖Receiver,不需要开启WAL机制,只要kafka中做了数据的复制,那么就可以通过kafka的副本进行恢复
  • 一次且仅一次的事务机制

3.两者对比

  • 基于receiver的方式,是使用kafka的高阶API来在zookeeper中保存消费过的offset的,这是消费kafka数据的传统方式.这种方式配合着WAL机制可以保证数据零丢失的高可靠性,但是却无法保证数据被处理一次且仅一次,可能会处理两次.因为spark和zookeeper之间可能是不同步的
  • 基于direct的方式,使用kafka的简单api,SparkStreaming自己就负责跟踪消费的offset,并保存在checkpoint.spark自己一定是同步的,因此可以保证数据是消费一次且仅消费一次
  • 在实际生产环境中大都用Direct方式

二.Spark Streaming窗口函数的原理

  • 窗口函数就是在原来定义的SparkStreaming计算批次大小的基础上再次进行封装,每次计算多个批次的数据,同时还需要传递一个滑动步长的参数,用来设置当次计算任务完成之后下一次从什么地方开始计算
  • 图中time1就是SparkStreaming计算批次大小,虚线框以及实线大框就是窗口的大小,必须为批次的整数倍.虚线框到大实线框的距离(相隔多少批次),就是滑动步长
    在这里插入图片描述

三.spark streaming 容错原理

spark streaming的一个特点就是高容错

  • 首先spark rdd就有容错机制,每一个rdd都是不可变的分布式可重算的数据集,其记录这确定性的操作血统,所以只要输入数据是可容错的,那么任意一个rdd的分区出错或不可用,都是可以利用原始输入数据通过转换操作而重新计算的
  • 预写日志通常被用于数据库和文件系统中,保证数据操作的持久性.预写日志通常是先将操作写入到一个持久可靠的日志文件中,然后才对数据施加该操作,当加入施加操作中出现了异常,可以通过读取日志文件并重新施加该操作
  • 另外接收数据的正确性只在数据被预写到日志以后接收器才会确认,已经缓存但还没保存的数据可以在driver重新启动后由数据源再发送一次,这两个机制确保了零数据丢失,所有数据或从日志中恢复或者由数据源重发

猜你喜欢

转载自blog.csdn.net/sun_0128/article/details/107974157