spark streaming调优

防止流量激增,导致程序过载

关于流量激增,可以通过设置Spark Streaming Backpressure。
反压机制(back-pressure),通过动态控制数据接收速率来适配集群数据处理能力。属性“spark.streaming.backpressure.enabled”来控制是否启用backpressure机制,默认值false,即不启用。

 sparkConf.set("spark.streaming.backpressure.enabled",”true”)

关于反压的具体讲解,请移步:Spark Streaming Backpressure分析

除了动态控制数据接收速率来适配集群数据处理能力,还可以通过设置spark.streaming.kafka.maxRatePerPartition参数来限制每次作业中每个 Kafka 分区最多读取的记录条数。这种方法虽然可以通过限制接收速率,来适配当前的处理能力。

 sparkConf.set("spark.streaming.kafka.maxRatePerPartition",10)

每批次最大处理的数据量= spark.streaming.kafka.maxRatePerPartition的值 * kafka partition的数量* 批处理间隔时间(单位:秒)
例:10分钟的吞吐量控制在1000,0000,kafka分区是10个。
spark.streaming.kafka.maxRatePerPartition=1680

通常spark.streaming.kafka.maxRatePerPartition和spark.streaming.backpressure.enabled是一起使用的,通过spark.streaming.kafka.maxRatePerPartition控制流处理启动时,处理的第一批数据,然后 反压 控制后续的处理的数据量。

对被操作频繁的RDD进行持久化

对rdd的操作原则,就是一个字 ‘

  1. 避免创建重复的RDD
  2. 尽可能复用同一个RDD
  3. 对被操作频繁的RDD进行持久化

上述第一点,第二点是写代码时候要注意的选项,而关于第三点的持久化建议是使用

 rdd.cache()

cache()是spark的源码定义是 MEMORY_ONLY,而在生产环境,面对意外时,内存可能不足以执行cache()操作,所以在这里建议使用MEMORY_AND_DISK_SER,通过序列化节省空间,缺点是性能的开销。

 rdd.persist(StorageLevel.MEMORY_AND_DISK_SER)
持久化级别含义解释
MEMORY_ONLY使用未序列化的Java对象格式,将数据保存在内存中。如果内存不够存放所有的数据,则数据可能就不会进行持久化。那么下次对这个RDD执行算子操作时,那些没有被持久化的数据,需要从源头处重新计算一遍。这是默认的持久化策略,使用cache()方法时,实际就是使用的这种持久化策略。
MEMORY_AND_DISK使用未序列化的Java对象格式,优先尝试将数据保存在内存中。如果内存不够存放所有的数据,会将数据写入磁盘文件中,下次对这个RDD执行算子时,持久化在磁盘文件中的数据会被读取出来使用
MEMORY_ONLY_SER基本含义同MEMORY_ONLY。唯一的区别是,会将RDD中的数据进行序列化,RDD的每个partition会被序列化成一个字节数组。这种方式更加节省内存,从而可以避免持久化的数据占用过多内存导致频繁GC。
MEMORY_AND_DISK_SER基本含义同MEMORY_AND_DISK。唯一的区别是,会将RDD中的数据进行序列化,RDD的每个partition会被序列化成一个字节数组。这种方式更加节省内存,从而可以避免持久化的数据占用过多内存导致频繁GC。
MEMORY_ONLY_2,MEMORY_AND_DISK_2,对于上述任意一种持久化策略,如果加上后缀_2,代表的是将每个持久化的数据,都复制一份副本,并将副本保存到其他节点上。这种基于副本的持久化机制主要用于进行容错。假如某个节点挂掉,节点的内存或磁盘中的持久化数据丢失了,那么后续对RDD计算时还可以使用该数据在其他节点上的副本。如果没有副本的话,就只能将这些数据从源头处重新计算一遍了。

关于持久化级别,通常不建议使用DISK_ONLY和后缀为_2的级别:因为完全基于磁盘文件进行数据的读写,会导致性能急剧降低,有时还不如重新计算一次所有RDD。后缀为_2的级别,必须将所有数据都复制一份副本,并发送到其他节点上,数据复制以及网络传输会导致较大的性能开销,除非是要求作业的高可用性,否则不建议使用。

使用map-side预聚合的shuffle操作

如果因为业务需要,一定要使用shuffle操作,无法用map类的算子来替代,那么尽量使用可以map-side预聚合的算子。
所谓的map-side预聚合,说的是在每个节点本地对相同的key进行一次聚合操作,类似于MapReduce中的本地combiner。map-side预聚合之后,每个节点本地就只会有一条相同的key,因为多条相同的key都被聚合起来了。其他节点在拉取所有节点上的相同key时,就会大大减少需要拉取的数据数量,从而也就减少了磁盘IO以及网络传输开销。通常来说,在可能的情况下,建议使用reduceByKey或者aggregateByKey算子来替代掉groupByKey算子。因为reduceByKey和aggregateByKey算子都会使用用户自定义的函数对每个节点本地的相同key进行预聚合。而groupByKey算子是不会进行预聚合的,全量的数据会在集群的各个节点之间分发和传输,性能相对来说比较差。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值