Spark学习02(Spark里的各种算子+RDD持久化-persist+RDD持久化-检查点+RDD共享变量)

一、各种算子的使用

转换含义
map(func)返回一个新的RDD,该RDD由每一个输入元素经过func函数转换后组成
filter(func)返回一个新的RDD,该RDD由经过func函数计算后返回值为true的输入元素组成
flatMap(func)类似于map,但是每一个输入元素可以被映射为0或多个输出元素(所以func应该返回一个序列,而不是单一元素)
mapPartitions(func)类似于map,但独立地在RDD的每一个分片上运行,因此在类型为T的RDD上运行时,func的函数类型必须是Iterator[T] => Iterator[U]
mapPartitionsWithIndex(func)类似于mapPartitions,但func带有一个整数参数表示分片的索引值,因此在类型为T的RDD上运行时,func的函数类型必须是(Int, Iterator[T]) => Iterator[U]
sample(withReplacement, fraction, seed)根据fraction指定的比例对数据进行采样,可以选择是否使用随机数进行替换,seed用于指定随机数生成器种子
union(otherDataset)对源RDD和参数RDD求并集后返回一个新的RDD
intersection(otherDataset)对源RDD和参数RDD求交集后返回一个新的RDD
distinct([numTasks]))对源RDD进行去重后返回一个新的RDD
groupByKey([numTasks])在一个(K,V)的RDD上调用,返回一个(K, Iterator[V])的RDD
reduceByKey(func, [numTasks])在一个(K,V)的RDD上调用,返回一个(K,V)的RDD,使用指定的reduce函数,将相同key的值聚合到一起,与groupByKey类似,reduce任务的个数可以通过第二个可选的参数来设置
aggregateByKey(zeroValue)(seqOp, combOp, [numTasks])相同的Key值进行聚合操作,在聚合过程中同样使用了一个中立的初始值zeroValue:中立值,定义返回value的类型,并参与运算seqOp:用来在同一个partition中合并值combOp:用来在不同partiton中合并值
sortByKey([ascending], [numTasks])在一个(K,V)的RDD上调用,K必须实现Ordered接口,返回一个按照key进行排序的(K,V)的RDD
sortBy(func,[ascending], [numTasks])与sortByKey类似,但是更灵活
join(otherDataset, [numTasks])在类型为(K,V)和(K,W)的RDD上调用,返回一个相同key对应的所有元素对在一起的(K,(V,W))的RDD
cogroup(otherDataset, [numTasks])在类型为(K,V)和(K,W)的RDD上调用,返回一个(K,(Iterable,Iterable))类型的RDD
cartesian(otherDataset)笛卡尔积
pipe(command, [envVars])将一些shell命令用于Spark中生成新的RDD
coalesce(numPartitions**)**重新分区
repartition(numPartitions)重新分区
repartitionAndSortWithinPartitions(partitioner)重新分区和排序
3.25.18 Action算子

在RDD上运行计算,并返回结果给Driver或写入文件系统

动作含义
reduce(func)通过func函数聚集RDD中的所有元素,这个功能必须是可交换且可并联的
collect()在驱动程序中,以数组的形式返回数据集的所有元素
count()返回RDD的元素个数
first()返回RDD的第一个元素(类似于take(1))
take(n)返回一个由数据集的前n个元素组成的数组
takeSample(withReplacement,num, [seed])返回一个数组,该数组由从数据集中随机采样的num个元素组成,可以选择是否用随机数替换不足的部分,seed用于指定随机数生成器种子
takeOrdered(n, [ordering])takeOrdered和top类似,只不过以和top相反的顺序返回元素
saveAsTextFile(path)将数据集的元素以textfile的形式保存到HDFS文件系统或者其他支持的文件系统,对于每个元素,Spark将会调用toString方法,将它装换为文件中的文本
saveAsSequenceFile(path)将数据集中的元素以Hadoop sequencefile的格式保存到指定的目录下,可以使HDFS或者其他Hadoop支持的文件系统。
saveAsObjectFile(path)
countByKey()针对(K,V)类型的RDD,返回一个(K,Int)的map,表示每一个key对应的元素个数。
foreach(func)在数据集的每一个元素上,运行函数func进行更新。

二、RDD的持久化

cache、persist、checkpoint

2.1 RDD的持久化(缓存)

cache和persist都是用于将一个RDD进行缓存。在该数据上的其他 action 操作将直接使用内存中的数据,这样在之后使用的过程中就不需要重新计算了,可以大大节省程序运行时间。


cache()方法表示:使用非序列化的方式将RDD中的数据全部尝试持久化到内存中。

persist()方法表示:手动选择持久化级别,并使用指定的方式进行持久化。


RDD可以使用persist()方法或cache方法进行持久化。数据将会在第一次action操作时进行计算,并缓存在节点的内存中。下一次的action直接调用这个缓存。

在 shuffle 操作中(例如 reduceByKey),即便是用户没有调用 persist 方法,Spark 也会自动缓存部分中间数据。这么做的目的是,在 shuffle 的过程中某个节点运行失败时,不需要重新计算所有的输入数据。

几种存储级别

MEMORY_ONLY: 将 RDD 以反序列化 Java 对象的形式存储在 JVM 中。如果内存空间不够, 部分数据分区将不再缓存,在每次需要用到这些数据时重新进行计算。这是默认的级别

MEMORY_AND_DISK : 将 RDD 以反序列化 Java 对象的形式存储在 JVM 中。如果内存空间不够,将未缓存的数据分区存储到磁盘,在需要使用这些分区时从磁盘读取。

MEMORY_ONLY_SER : 将 RDD 以序列化的 Java 对象的形式进行存储(每个分区为一个 byte 数组)。这种方式会比反序列化对象的方式节省很多空间,尤其是在使用 fast serializer时会节省更多的空间,但是在读取时会增加 CPU 的计算负担。

MEMORY_AND_DISK_SER : 类似于 MEMORY_ONLY_SER ,但是溢出的分区会存储到磁盘,而不是在用到它们时重新计算。

DISK_ONLY: 只在磁盘上缓存 RDD。

MEMORY_ONLY_2,MEMORY_AND_DISK_2,等等: 与上面的级别功能相同,只不过每个分区在集群中两个节点上建立副本。

OFF_HEAP: 类似于 MEMORY_ONLY_SER ,但是将数据存储在 off-heap memory,这需要启动 off-heap 内存。

通常不建议使用DISK_ONLY和后缀为_2的级别:

因为完全基于磁盘文件进行数据的读写,会导致性能急剧降低,有时还不如重新计算一次所有RDD。

后缀为_2的级别,必须将所有数据都复制一份副本,并发送到其他节点上,数据复制以及网络传输会导致较大的性能开销,除非是要求作业的高可用性,否则不建议使用。


参考:https://blog.csdn.net/u010003835/article/details/83271427

存储级别的参数:

1、_useDisk:使用磁盘
2、_useMemory:使用内存
3、_useOffHeap:使用堆外存,这是Java虚拟机里面的概念,堆外内存意味着把内存对象分配在Java虚拟机的堆以外的内存,这些内存直接受操作系统管理(而不是虚拟机)。这样做的结果就是能保持一个较小的堆,以减少垃圾收集对应用的影响。
4、_deserialized:使用反序列化,其逆过程序列化(Serialization)是java提供的一种机制,将对象表示成一连串的字节;而反序列化就表示将字节恢复为对象的过程。序列化是对象永久化的一种机制,可以将对象及其属性保存起来,并能在反序列化后直接恢复这个对象
5、_replication:副本数,默认是一个

作用:可以对公共代码块进行持久化,复用代码,提高效率,同时持久化机制,一定要触发Action算子,才会有效(数据将会在第一次 action 操作时进行计算,并缓存在节点的内存中)

cache和persist主要在于使用过程中,如果内存充足,可以直接使用cache,反之要选择其他级别的话,那么用persist进行级别更换,推荐使用内存+磁盘

看源码:
在这里插入图片描述
通过源码可以看出cache()是persist()的简化方式,调用persist的无参版本,也就是调用persist(StorageLevel.MEMORY_ONLY),cache只有一个默认的缓存级别MEMORY_ONLY,即将数据持久化到内存中,而persist可以通过传递一个 StorageLevel 对象来设置缓存的存储级别。

如果持久化使用结束,程序依然运行,那么需要释放掉缓存,节省空间,用 unpersist()

注意:cache()和persist()的使用是有规则的:
必须在transformation或者textfile等创建一个rdd之后,直接连续调用cache()或者persist()才可以,如果先创建一个rdd,再单独另起一行执行cache()或者persist(),是没有用的,而且会报错,大量的文件会丢失。

2.2 RDD的持久化(检查点)

检查点(本质是通过将RDD写入Disk做检查点) 是为了通过lineage做容错的辅助,lineage过长会造成容错成本过高,这样就不如在中间阶段做检查点容错,如果之后有节点出现问题而丢失分区,从做检查点的RDD开始重做Lineage,就会减少开销。检查点通过将数据写入到HDFS文件系统实现了RDD的检查点功能。

//设置检查点
rdd.checkpoint

当使用了checkpoint后,数据被保存到HDFS,此RDD的依赖关系也会丢掉,因为数据已经持久化到HDFS,所以不需要重新计算,无论是cache或checkpoint缓存了数据,若数据丢失是自动恢复的,checkpoint的数据需要手动清除而cache的数据是自动清除的(任务结束)
由于是将RDD写入磁盘,因此非常占用资源,不建议经常使用。

什么时候使用checkpoint

1.某步骤计算特别耗时

2.计算链条特别长

3.发生shuffle之后

建议使用cache或是persist模式因为,不需要创建存储位置,并且默认存储到内存中计算速度快,而checkpoint需要手动创建存储位置和手动删除数据.若数据量非常庞大建议改用chechpoint.

三、RDD的共享变量

  1. 广播变量(Broadcast)
 //将字典文件广播到各个节点的executor
  private val board: Broadcast[Array[(String, String, String)]] =
   sc.broadcast(dict.collect())

  private val value: RDD[(String, Int)] = ip.map(x => {
    val longIp = ip2Long(x)
    //获取广播变量的值
    val arrInfo: Array[(String, String, String)] = board.value
    val i: String = binarySearch(arrInfo, longIp)
    (i, 1)
  })

广播变量可以将Driver创建的变量广播到每个节点的executor中,作为缓存使用,然后每个Task不需要每次都去拉取Driver的变量,这样减少的大量网络IO和磁盘IO,节省时间,减低资源消耗,同时减少每个Task的冗余性,提升效率

释放广播变量 unpersist

使用场景:比如在本地有字典文件,需要读取,并且不是太大,那么此时可以使用广播变量将其广播到executor内存中,供给每个Task进行使用,减少数据冗余性,提高效率

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值