作者:个推数据研发工程师 学长

 

 

1 业务背景

 

随着大数据的快速发展,业务场景越来越复杂,离线式的批处理框架MapReduce已经不能满足业务,大量的场景需要实时的数据处理结果来进行分析、决策。Spark Streaming是一种分布式的大数据实时计算框架,他提供了动态的,高吞吐量的,可容错的流式数据处理,不仅可以实现用户行为分析,还能在金融、舆情分析、网络监控等方面发挥作用。个推开发者服务——消息推送“应景推送”正是应用了Spark Streaming技术,基于大数据分析人群属性,同时利用LBS地理围栏技术,实时触发精准消息推送,实现用户的精细化运营。此外,个推在应用Spark Streaming做实时处理kafka数据时,采用Direct模式代替Receiver模式的手段,实现了资源优化和程序稳定性提升。

 

本文将从Spark Streaming获取kafka数据的两种模式入手,结合个推实践,带你解读Receiver和Direct模式的原理和特点,以及从Receiver模式到Direct模式的优化对比。

 

 

2 两种模式的原理和区别

 

Receiver模式

 

1. Receiver模式下的运行架构

 



1)InputDStream: 从流数据源接收的输入数据。

 

2)Receiver:负责接收数据流,并将数据写到本地。

 

3)Streaming Context:代表SparkStreaming,负责Streaming层面的任务调度,生成jobs发送到Spark engine处理。

 

4)Spark Context: 代表Spark Core,负责批处理层面的任务调度,真正执行job的Spark engine。

 

2. Receiver从kafka拉取数据的过程

 



 

该模式下:

 

1)在executor上会有receiver从kafka接收数据并存储在Spark executor中,在到了batch时间后触发job去处理接收到的数据,1个receiver占用1个core;

 

2)为了不丢数据需要开启WAL机制,这会将receiver接收到的数据写一份备份到第三方系统上(如:HDFS);

 

3)receiver内部使用kafka High Level API去消费数据及自动更新offset。

 

Direct模式

 

1. Direct模式下的运行架构

 

与receiver模式类似,不同在于executor中没有receiver组件,从kafka拉去数据的方式不同。

 

2. Direct从kafka拉取数据的过程

 



该模式下:

 

1)没有receiver,无需额外的core用于不停地接收数据,而是定期查询kafka中的每个partition的最新的offset,每个批次拉取上次处理的offset和当前查询的offset的范围的数据进行处理;

 

2)为了不丢数据,无需将数据备份落地,而只需要手动保存offset即可;

 

3)内部使用kafka simple Level API去消费数据, 需要手动维护offset,kafka zk上不会自动更新offset。

 

Receiver与Direct模式的区别

 

1.前者在executor中有Receiver接受数据,并且1个Receiver占用一个core;而后者无Receiver,所以不会暂用core;

 

2.前者InputDStream的分区是 num_receiver *batchInterval/blockInteral,后者的分区数是kafka topic partition的数量。Receiver模式下num_receiver的设置不合理会影响性能或造成资源浪费;如果设置太小,并行度不够,整个链路上接收数据将是瓶颈;如果设置太多,则会浪费资源;

 

3.前者使用zookeeper来维护consumer的偏移量,而后者需要自己维护偏移量;

 

4.为了保证不丢失数据,前者需要开启WAL机制,而后者不需要,只需要在程序中成功消费完数据后再更新偏移量即可。

 

3 Receiver改造成Direct模式

 

个推使用Spark Streaming做实时处理kafka数据,先前使用的是receiver模式;

 

receiver有以下特点

 

1.receiver模式下,每个receiver需要单独占用一个core;

 

2.为了保证不丢失数据,需要开启WAL机制,使用checkpoint保存状态;

 

3.当receiver接受数据速率大于处理数据速率,导致数据积压,最终可能会导致程序挂掉。

 

由于以上特点,receiver模式下会造成一定的资源浪费;使用checkpoint保存状态, 如果需要升级程序,则会导致checkpoint无法使用;第3点receiver模式下会导致程序不太稳定;并且如果设置receiver数量不合理也会造成性能瓶颈在receiver。为了优化资源和程序稳定性,应将receiver模式改造成direct模式。

 

修改方式如下:

 

1. 修改InputDStream的创建

 

将receiver的:

val kafkaStream = KafkaUtils.createStream(streamingContext,
[ZK quorum], [consumer group id], [per-topic number of Kafka partitions to consume])

改成direct的:

val directKafkaStream = KafkaUtils.createDirectStream[
[key class], [value class], [key decoder class], [value decoder class] ](
streamingContext, [map of Kafka parameters], [set of topics to consume])

 

2. 手动维护offset

 

receiver模式代码:

(receiver模式不需要手动维护offset,而是内部通过kafka consumer high level API 提交到kafka/zk保存)

kafkaStream.map {
...
}.foreachRDD { rdd =>
// 数据处理
doCompute(rdd)
}

direct模式代码:

directKafkaStream.map {
...
}.foreachRDD { rdd =>
// 获取当前rdd数据对应的offset
val offsetRanges = rdd.asInstanceOf[HasOffsetRanges].offsetRanges
// 数据处理
doCompute(rdd)
// 自己实现保存offset
commitOffsets(offsetRanges)
}

 

4 其他优化点

 

1. 在receiver模式下

 

1)拆分InputDStream,增加Receiver,从而增加接收数据的并行度;

 

2)调整blockInterval,适当减小,增加task数量,从而增加并行度(在core的数量>task数量的情况下);

 

3)如果开启了WAL机制,数据的存储级别设置为MOMERY_AND_DISK_SER。

 

2.数据序列化使用Kryoserializationl,相比Java serializationl 更快,序列化后的数据更小;

 

3.建议使用CMS垃圾回收器降低GC开销;

 

4.选择高性能的算子(mapPartitions, foreachPartitions, aggregateByKey等);

 

5.repartition的使用:在streaming程序中因为batch时间特别短,所以数据量一般较小,所以repartition的时间短,可以解决一些因为topicpartition中数据分配不均匀导致的数据倾斜问题;

 

6.因为SparkStreaming生产的job最终都是在sparkcore上运行的,所以sparkCore的优化也很重要;

 

7.BackPressure流控

 

1)为什么引入Backpressure?

当batch processing time>batchinterval 这种情况持续过长的时间,会造成数据在内存中堆积,导致Receiver所在Executor内存溢出等问题;

 

2)Backpressure:根据JobScheduler反馈作业的执行信息来动态调整数据接收率;

 

3)配置使用:

spark.streaming.backpressure.enabled
含义: 是否启用 SparkStreaming内部的backpressure机制,
默认值:false ,表示禁用 spark.streaming.backpressure.initialRate
含义: receiver 为第一个batch接收数据时的比率 spark.streaming.receiver.maxRate
含义: receiver接收数据的最大比率,如果设置值<=0, 则receiver接收数据比率不受限制 spark.streaming.kafka.maxRatePerPartition
含义: 从每个kafka partition中读取数据的最大比率

8.speculation机制

 

spark内置speculation机制,推测job中的运行特别慢的task,将这些task kill,并重新调度这些task执行。

默认speculation机制是关闭的,通过以下配置参数开启:

spark.speculation=true

 

注意:在有些情况下,开启speculation反而效果不好,比如:streaming程序消费多个topic时,从kafka读取数据直接处理,没有重新分区,这时如果多个topic的partition的数据量相差较大那么可能会导致正常执行更大数据量的task会被认为执行缓慢,而被中途kill掉,这种情况下可能导致batch的处理时间反而变长;可以通过repartition来解决这个问题,但是要衡量repartition的时间;而在streaming程序中因为batch时间特别短,所以数据量一般较小,所以repartition的时间短,不像spark_batch一次处理大量数据一旦repartition则会特别久,所以最终还是要根据具体情况测试来决定。

 

 

5 总结

 

将Receiver模式改成Direct模式,实现了资源优化,提升了程序的稳定性,缺点是需要自己管理offset,操作相对复杂。未来,个推将不断探索和优化Spark Streaming技术,发挥其强大的数据处理能力,为建设实时数仓提供保障。

Spark Streaming的优化之路—从Receiver到Direct模式的更多相关文章

  1. Spark Streaming性能优化: 如何在生产环境下应对流数据峰值巨变

    1.为什么引入Backpressure 默认情况下,Spark Streaming通过Receiver以生产者生产数据的速率接收数据,计算过程中会出现batch processing time > ...

  2. Spark Streaming性能优化系列-怎样获得和持续使用足够的集群计算资源?

    一:数据峰值的巨大影响 1. 数据确实不稳定,比如晚上的时候訪问流量特别大 2. 在处理的时候比如GC的时候耽误时间会产生delay延迟 二:Backpressure:数据的反压机制 基本思想:依据上 ...

  3. 【转】Spark Streaming 实时计算在甜橙金融监控系统中的应用及优化

    系统架构介绍 整个实时监控系统的架构是先由 Flume 收集服务器产生的日志 Log 和前端埋点数据, 然后实时把这些信息发送到 Kafka 分布式发布订阅消息系统,接着由 Spark Streami ...

  4. 9. Spark Streaming技术内幕 : Receiver在Driver的精妙实现全生命周期彻底研究和思考

        原创文章,转载请注明:转载自 听风居士博客(http://www.cnblogs.com/zhouyf/)       Spark streaming 程序需要不断接收新数据,然后进行业务逻辑 ...

  5. spark streaming 3: Receiver 到 submitJobSet

     对于spark streaming来说,receiver是数据的源头.spark streaming的框架上,将receiver替换spark-core的以磁盘为数据源的做法,但是数据源(如监听某个 ...

  6. (转)用Flink取代Spark Streaming!知乎实时数仓架构演进

    转:https://mp.weixin.qq.com/s/e8lsGyl8oVtfg6HhXyIe4A AI 前线导读:“数据智能” (Data Intelligence) 有一个必须且基础的环节,就 ...

  7. Spark Streaming的简单介绍

    本文讲解Spark流数据处理之Spark Streaming.本文的写作时值Spark 1.6.2发布之际,Spark 2.0预览版也已发布,Spark发展如此迅速,请随时关注Spark Stream ...

  8. 【慕课网实战】Spark Streaming实时流处理项目实战笔记十三之铭文升级版

    铭文一级: 第10章 Spark Streaming整合Kafka spark-submit \--class com.imooc.spark.KafkaReceiverWordCount \--ma ...

  9. Spark Streaming简介及原理

    简介: SparkStreaming是一套框架. SparkStreaming是Spark核心API的一个扩展,可以实现高吞吐量的,具备容错机制的实时流数据处理. 支持多种数据源获取数据: Spark ...

随机推荐

  1. Insertion Sort List(单链表插入排序)

    来源:https://leetcode.com/problems/insertion-sort-list Sort a linked list using insertion sort. 方法: 1. ...

  2. 递归法求组合数C(m,n)

    假设这样一个数组: 1 2 3 4 5 n=5 若 m=3 也就是要求C(3,5) 首先先选第一个数 1 那么剩下的工作就是在2-5之间选择2个数 如果我们没有选择第一个数 选第二个数2 那么剩下的工 ...

  3. 主机(windows10)虚拟机(ubuntu18)arm板(linux3.4)相互ping通

    实际中在主机上安装虚拟机,并在主机上通过网线连接arm板进行调试. 用网线将主机和arm板直接物理连接,且主机和arm必须处于同一个网段.(我们知道主机中的网卡具有路由器的功能) 其中arm板IP地址 ...

  4. Luogu p2456 二进制方程

    这是一道我也不知道我gu了多久的题目 (然鹅还有n多任务没有完成) 反正--我太难了 好了言归正传,题目链接 是一道校内测的题目(现在应该没有人没考了吧?) 思路的话,是神仙并查集√ 觉得虽然并查集很 ...

  5. 洛谷P2507 [SCOI2008]配对 题解(dp+贪心)

    洛谷P2507 [SCOI2008]配对 题解(dp+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1299251 链接题目地址:洛谷P2507 [S ...

  6. 安装最新版Elasticsearch报错

    1 问题:ERROR: bootstrap checks failed max file descriptors [4096] for elasticsearch process likely too ...

  7. MVCC/分布式事务简介

    之前我们学习了RocksDB,但这还只是一个最基础的存储引擎.如果想把它在生产环境中用起来,还需要解决很多问题: 如何从单机扩展到分布式? 如何实现事务,并对事务进行并发控制? 用户接口能不能高级一点 ...

  8. MySQL第一讲 一一一一 数据库入门

    一. MySQL简介与安装 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品.MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方 ...

  9. django基础篇04-自定义simple_tag和fitler

    自定义simple_tag app目录下创建templatetags目录 templatetags目录下创建xxpp.py 创建template对象register,注意变量名必须为register ...

  10. css实现div内凹角样式

    平常的开发中我们一般使用到圆角都是外凸的,即border-radius属性.而如果有内凹角的情况,我们一般的考虑实现方法有2种.一种是直接使用背景图片,一种是使用css. 用到的属性则是backgro ...