SparkStreaming2.2 + Kafka0.8

痞子三分冷 提交于 2020-01-01 23:08:03

SparkStreaming2.2(包含以前版本)+Kafka0.8

1. receiver模式

(不管需不需要都会传输数据)

receiver模式原理图

在这里插入图片描述
在这里插入图片描述

receiver模式流程:
  1. 在SparkStreaming程序运行起来后,Executor中会有receiver task接收kafka推送过来的数据。数据会被持久化,默认级别为MEMORY_AND_DISK_SER_2,这个级别也可以修改。
  2. receiver task对接收过来的数据进行存储和备份,这个过程会有节点之间的数据传输。(此时开启了WAL也会备份到HDFS上)
  3. 备份完成后去zookeeper中更新消费偏移量offset,
  4. 然后向Driver中的receiver tracker汇报数据的位置。
  5. 最后Driver根据数据本地化将task分发到不同节点上执行。

receiver模式中存在的问题
  1. 数据丢失问题
    当 Driver进程挂掉后,Driver中的Executor进程都会被杀掉,若此时任务未计算完,会造成数据找不到的问题,相当于数据丢失.
  • 解决:开启WAL(write ahead log)预写日志机制,在数据进行备份的时候会在hdfs上备份一份,这样就保证了数据的安全性,但是HDFS写入比较消耗性能,需要在数据备份完成之后才能进行zookeeper偏移量更新,位置汇报等等,会增加任务执行时间,我们可以将MEMORY_AND_DISK_SER_2 改成 MEMORY_AND_DISK_SER 来略微提升一点点性能.
  1. 开启WAL机制造成的数据重复消费问题
    开启WAL机制,如果数据备份到HDFS上面后,此时要提交偏移量到zookeeper上,如果此时Driver挂掉了,则会造成数据偏移量提交失败.重新启动Driver之后,会先读取HDFS上数据,在读取zookeeper上的偏移量,然后读取kafka上的数据,此时会造成数据重复消费.

receiver代码

receiver的并行度设置

receiver的并行度是由spark.streaming.blockInterval来决定的,默认为200ms,假设batchInterval为5s,那么每隔blockInterval就会产生一个block,这里就对应每批次产生RDD的partition,这样5秒产生的这个Dstream中的这个RDD的partition为25个,并行度就是25。如果想提高并行度可以减少blockInterval的数值,但是最好不要低于50ms

2. Driect模式

主动获取数据

Direct模式理解

SparkStreaming + kafka 的Driect模式就是将kafka看成存数据的一方,不是被动接收数据,而是主动去取数据。消费者偏移量也不是用zookeeper来管理,而是SparkStreaming内部对消费者偏移量自动来维护,默认消费偏移量是在内存中,当然如果设置了checkpoint目录,那么消费偏移量也会保存在checkpoint中。当然也可以实现用zookeeper来管理。

模式原理图:

在这里插入图片描述

Direct模式并行度设置

Direct模式的并行度是由读取的kafka中topic的partition数决定的。

Direct模式代码(见代码)

3. 相关配置

预写日志模式(WAL模式)

spark.streaming.receiver.writeAheadLog.enable  默认false没有开启

blockInterval (receiver模式下的参数)
控制并行度

spark.streaming.blockInterval  默认200ms

反压机制:
通过动态控制数据接收速率来适配集群数据处理能力

spark.streaming.backpressure.enabled 默认false

最大吞吐量限制
Receiver模式:

spark.streaming.receiver.maxRate  默认没有设置

Direct模式:

spark.streaming.kafka.maxRatePerPartition

优雅的停止sparkstream :

spark.streaming.stopGracefullyOnShutdown 设置成true

优雅的关闭
kill -15/sigterm driverpid

4. 总结SparkStreaming2.2(包含以前) + Kafka0.8.2

Receiver模式

  • receiver模式采用了Receiver接收器模式,需要一个线程一直接收数据,将数据接收到Executor中,默认存储级别是MEMORY_AND_DISK_SER_2
  • receiver模式自动使用zookeeper管理消费者offset
  • receiver模式底层读取Kafka 采用High Level Consumer API 实现,这种模式不关心offset,只要数据。
  • receiver模式当Driver挂掉时,有丢失数据问题,可以开启WAL机制 避免丢失数据,但是开启之后加大了数据处理延迟 ,并且存在数据重复消费风险。
  • receiver模式并行度由spark.streaming.blockInterval = 200ms ,可以减少这个参数增大并行度,最小不能低于50ms
  • Receiver模式不被使用
    • 被动将数据接收到Executor,当有任务堆积时,数据存储问题
    • 这种模式不能手动维护消费者offset
    • 开启WAL机制,性能会慢,不开又可能数据丢失,开了之后还可能数据重复消费

Direct模式

  • direct模式没有使用receiver接收器模式,每批次处理数据直接获取当前批次数据处理
  • direct模式没有使用zookeeper管理消费者offset,使用的是Spark自己管理,默认存在内存中,可以设置checkpoint,也会保存到checkpoint中一份
  • direct模式底层读取Kafka使用 Simple Consumer API ,可以手动维护消费者offset
  • direct模式并行度 与读取的topic的partition 一一对应
  • 可以使用设置checkpoint的方式管理消费者offset, 使用StreamingContext.getOrCreate(ckDir,CreateStreamingContext) 恢复 。这种方式有两种缺点:
    第一:当代码逻辑改变时,无法从checkpoint中来恢复offset.
    第二:当从checkpoint中恢复数据时,有可能造成重复的消费,需要我们写代码来保证数据的输出幂等 开启事务等方法
  • 如果代码逻辑改变,就不能使用checkpoint模式管理offset,可以手动维护消费者offset,可以将offset存储到外部系统,如redis
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!