Spark惰性求值与持久化(缓存)

惰性求值

惰性求值意味着当我们对RDD调用转化操作(例如调用map()时),操作不会立即执行。相反,Spark会在内部记录下所要求执行的操作的相关信息。我们不应该把RDD看作存放着特定数据的数据集,而最好把每个RDD当作我们通过转化操作构建出来的、记录如何计算数据的指令列表。把数据读取到RDD的操作也同样是惰性的。因此,当我们调用sc.textFile()时,数据并没有读取进来,而是在必要时才会读取。和转化操作一样的是,读取数据的操作也有可能会多次执行。

Spark使用惰性求值,这样就可以把一些操作合并到一起来减少计算数据的步骤。

scala> val lines = sc.textFile("README.md")
lines: spark.RDD[String] = MappedRDD[...]

scala> val pythonLines = lines.filter(line => line.contains("Python"))
pythonLines: spark.RDD[String] = FilteredRDD[...]

scala> pythonLines.first()
res0: String = ## Interactive Python Shell

比如在上述语句中,我们以一个文本文件定义了数据,然后把其中包含Python的行筛选出来。如果Spark在我们运行lines = s.textFile()时就把文件中所有的行都读取并存储起来,就会消耗很多存储空间,而我们马上就要筛选掉其中的很多数据。相反,一旦Spark了解了完整的转化操作链之后,它就可以只计算求结果时真正需要的数据。事实上,在行动操作first()中,Spark只需要扫描文件直到找到第一个匹配的行为为止,而不需要读取整个文件。

在类似Hadoop MapReduce的系统中,开发者常常花费大量时间考虑如何把操作组合到一起,以减少MapReduce的周期数。而在Spark中,写出一个非常复杂的映射并不见得能比使用很多简单的连续操作获得好很多的性能。

持久化(缓存)

如前所述,Spark RDD 是惰性求值的,而有时我们希望能多次使用同一个RDD。如果简单地对RDD 调用行动操作,Spark 每次都会重算RDD以及它的所有依赖。这在迭代算法中消耗格外大,因为迭代算法常常会多次使用同一组数据。下面就是先对RDD 作一次计数、再把该RDD 输出的一个小例子。

val input = sc.parallelize(List(1,3,5,7))
val result = input.map(x => x*x)
println(result.count())
println(result.collect().mkString(","))

为了避免多次计算同一个RDD,可以让Spark 对数据进行持久化。当我们让Spark 持久化存储一个RDD 时,计算出RDD 的节点会分别保存它们所求出的分区数据。如果一个有持久化数据的节点发生故障,Spark 会在需要用到缓存的数据时重算丢失的数据分区。如果希望节点故障的情况不会拖累我们的执行速度,也可以把数据备份到多个节点上。出于不同的目的,我们可以为RDD 选择不同的持久化级别。
在这里插入图片描述

val input = sc.parallelize(List(1,3,5,7))
val result = input.map(x => x * x)
result.persist(StorageLevel.DISK_ONLY)
println(result.count())
println(result.collect().mkString(","))

注意,我们在第一次对这个RDD 调用行动操作前就调用了persist() 方法。persist() 调
用本身不会触发强制求值。

如果要缓存的数据太多,内存中放不下,Spark 会自动利用最近最少使用(LRU)的缓存策略把最老的分区从内存中移除。对于仅把数据存放在内存中的缓存级别,下一次要用到已经被移除的分区时,这些分区就需要重新计算。但是对于使用内存与磁盘的缓存级别的分区来说,被移除的分区都会写入磁盘。不论哪一种情况,都不必担心你的作业因为缓存了太多数据而被打断。不过,缓存不必要的数据会导致有用的数据被移出内存,带来更多重算的时间开销。

最后,RDD 还有一个方法叫作unpersist(),调用该方法可以手动把持久化的RDD 从缓
存中移除。

参考 《Spark快速大数据分析》

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值