性能调优之在实际项目中分配更多资源
性能调优的王道,增加和分配更多的资源,性能和速度上的调优,是显而易见的,基本上在一定范围内,增加资源与性能的提升,是成正比的,写完一个spark作业以后 ,进行性能调优。 1.分配那些资源? executor, CPU per executor, memory per executor
2.在哪里分配这些资源? 提交shell脚本的时候
3.怎么调优,以及调优的原则? 第一种spark standalone,公司集群上,搭建一套spark集群技术心里应该清楚。 第二种,yarn,资源调度。应该去查看,你的spark作业,要提交到资源队列技术大概有多少资源? 一个原则,你能使用的资源能有多大,就尽量调节到最大。
4.为什么多分配这些资源以后我性能会得到提升?
性能调优之Spark并行度
Spark并行度,其实就是指的是spark作业中,各个stage的task数量,也就代表了spark作业的各个阶段的并行度。
如果不调节,并行度,导致并行度过低,会怎么样?
你的资源虽然分配足够了,但是问题是并行度没有与资源想匹配,导致你的资源分配浪费。
合理的并行度的设置,应该是要设置的足够大,大到可以完全合理的利用你的集群资源。
1.task数量,至少设置成与spark application的总CPU core数量相同
2.官方推荐,task数量,设置成为spark application总CPU core数量的2-3倍,
实际情况,与理想情况不同的,有些task会运行快一点,有些task可能会慢一点,如果你的task设置的和CPU core数量相同,可能会导致资源浪费。
3.如何设置一个 spark application的并行度? spark.default.parallelism参数,在conf中设置。
性能调优之RDD重构和持久化
1.默认情况下,多次对一个RDD执行算子,去获取不同的RDD,都会对这个RDD以及以前的父RDD,全部重新计算一次。
对于这种情况,是一定要避免的,一旦出现一个RDD重复计算,就会导致性能急剧降低。
2.RDD架构重构优化
尽量去复用RDD,差不多的RDD,可以抽取成为一个共同的RDD供后面的RDD计算,反复使用。
公共的RDD一定要实现持久化。持久化也就是说,将RDD的数据缓存到内存或者磁盘中,之后无论进行多少次计算,都直接取这个RDD的持久化的数据。
持久化,是可以进行序列化的。如果正常将持久化在内存,那么可能会导致内存的占用过大,这样的话,会知道内存溢出。
当内存无法支持公共RDD数量完全存放的时候,就优先考虑,使用序列化的方式在存内存存储。序列化的方式,唯一的缺点是在获取数据的时候,需要到反序列化。
如果序列化纯内存,只能内存+磁盘的序列化方式。
为了数据的高可靠性,而且内存充足可以使用双副本,进行持久化。持久化的双副本机制,因为机器宕机了,副本就丢了,需要重复机制,但是这样是针对你的资源很充分。
性能调优之在实际项目中广播大变量
默认情况下,task执行的算子中,使用外部的变量,每个task都会获取一份变量,有什么缺点?在什么情况下会出现性能上的优劣影响?
每一个task出现一份变量,极其消耗内存,有可能导致堆内存不足,频繁GC,以及RDD持久化部分写入到磁盘,从而导致磁盘IO的消耗等。
如何解决上述性能影响呢?
广播变量。广播变量在driver上会有一份初始的副本,第一个executor都有一个BlockManager负责管理某个内存和磁盘上的数据,
这个会在driver上拉去相应的广播变量,有可能会从远层的driver上获取变量副本,也有可能从距离比较近的其他节点获取。
广播变量的好处,不是每一个task一个变量副本,而是每一个executor一个变量副本,这样减少网络传输数据,也给减少了内存存储。
性能优化之在实际项目中使用Kryo序列化
默认情况下,spark内部使用java的序列化机器,objectOutPutStream/objectInPutStream对象输入输出流机制,
通过这种机制序列化,这种默认的序列化机制好处在于不必手动,但是缺点在于效率不高,占用内存比较大,。
Kryo序列化机制,速度快乐序列化之后数据更小,大概是java序列化机制的1/10,在序列化之后,可以让网络传输的数据变小,内存资源也变小。
kyro序列化机制: 1.算子函数中使用的外部变量 2.持久化RDD进行序列化 3.shuffle