5.RDD持久化

概述

今日目标:

  • RDD 持久化
    • RDD持久化原理
    • RDD持久化策略
    • 如何选择RDD持久化策略
    • 案例

相关文章如下:

RDD 持久化

RDD持久化原理

Spark中最重要的功能之一是跨操作在内存中持久化(或缓存)数据集。当持久化RDD时,每个节点将其计算的任何分区存储在内存中,针对一个RDD反复执行多个操作的场景,就只需要对RDD计算一次即可。这使得在接下来的数据处理中速度更快(通常超过10倍)。

正常情况下,RDD 的数据使用过后,内存中是不会一直保存的。

例如以下的操作,针对mapRDD需要多次使用

val dataRDD = sc.parallelize(Array(1,2,3,4))
val mapRDD = dataRDD.map(...)
mapRDD.foreach(...)
mapRDD.saveAsTextFile(...)
mapRDD.collect()

合理使用 RDD 持久化,在某些场景下,对 Spark 应用程序的性能有很大的提升,特别是对于迭代式算法快速交互应用来说,RDD 持久化,是非常的重要。

迭代式算法:迭代算法也称“辗转法”,是一种不断用变量的旧值递推出新值的解决问题的方法。

要持久化一个 RDD ,只需要调用它的 cache()persist() 方法就可以了。

cache()persist()的区别在于:
cache()persist()的一种简化方式,cache()的底层就是调用的persist()的无参版本,也就是调用persist(MEMORY_ONLY),将数据持久化到内存中。

如果需要从内存中清除缓存,那么可以使用unpersist()方法。

RDD持久化策略

下面来看一下目前 Spark 支持的一些持久化策略

策略介绍
MEMORY_ONLY以非序列化的方式持久化在JVM内存中
MEMORY_AND_DISK同上,但是当某些partition无法存储在内存中时,会持久化到磁盘中
MEMORY_ONLY_SERMEMORY_ONLY,但是会序列化
MEMORY_AND_DISK_SERMEMORY_AND_DSK,但是会序列化
DISK_ONLY以非序列化的方式完全存储到磁盘上
MEMORY_ONLY_2、MEMORY_AND_DISK_2等尾部加了2的持久化级别,表示会将持久化数据复制一份,保存到其他节点

补充说明:

  • MEMORY_ONLY:以非序列化的Java对象的方式持久化在JVM内存中。如果内存无法完全存储RDD所有的partition,那么那些没有持久化的partition就会在下一次需要使用它的时候,重新被计算。

  • MEMORY_AND_DISK:当某些partition无法存储在内存中时,会持久化到磁盘中。下次需要使用这些partition时,需要从磁盘上读取,不需要重新计算

  • MEMORY_ONLY_SER:同MEMORY_ONLY,但是会使用Java的序列化方式,将Java对象序列化后进行持久化。可以减少内存开销,但是在使用的时候需要进行反序列化,因此会增加CPU开销。

  • MEMORY_AND_DISK_SER:同MEMORY_AND_DSK。但是会使用序列化方式持久化Java对象。

  • DISK_ONLY:使用非序列化Java对象的方式持久化,完全存储到磁盘上。

  • MEMORY_ONLY_2、MEMORY_AND_DISK_2等:如果是尾部加了2的持久化级别,表示会将持久化数据复制一份,保存到其它节点,从而在数据丢失时,不需要重新计算,只需要使用备份数据即可。

如何选择RDD持久化策略

Spark提供了多种持久化级别,主要是为了在CPU内存消耗之间进行取舍。
下面是一些通用的持久化级别的选择建议:

  • 优先使用MEMORY_ONLY,纯内存速度最快,而且没有序列化不需要消耗CPU进行反序列化操作,缺点就是比较耗内存
  • MEMORY_ONLY_SER,将数据进行序列化存储,纯内存操作还是非常快,只是在使用的时候需要消耗CPU进行反序列化

注意:
如果需要进行数据的快速失败恢复,那么就选择带后缀为_2的策略,进行数据的备份,这样在失败时,就不需要重新计算了
能不使用DISK相关的策略,就不要使用,因为有的时候,从磁盘读取数据,还不如重新计算一次。

案例

代码如下:

object PersistRDDScala {
  def main(args: Array[String]): Unit = {
    var path = "/Users/hyl/Desktop/fun/sts/spark-demo/hello.txt"
    if (args.length == 1) {
      path = args(0)
    }
    val conf = new SparkConf()
    conf
      // 设置任务名称
      .setAppName("WordCount")
      // local 表示本地运行
      .setMaster("local")
    val linesRDD = new SparkContext(conf).textFile(path)
    var start_time = System.currentTimeMillis()
    linesRDD.flatMap(_.split(" ")).map((_, 1)).reduceByKey(_ + _).foreach(println _)
    var end_time = System.currentTimeMillis()
    println("第一次耗时:" + (end_time - start_time))

    start_time = System.currentTimeMillis()
    linesRDD.flatMap(_.split(" ")).map((_, 1)).reduceByKey(_ + _).foreach(println _)
    end_time = System.currentTimeMillis()
    println("第二次耗时:" + (end_time - start_time))
  }
}

在这里插入图片描述
在这里插入图片描述
RDD 持久化代码如下:

val linesRDD = new SparkContext(conf).textFile(path).cache()

在这里插入图片描述
在这里插入图片描述
性能提升不明显,那是因为计算的数据量不够大,生产中,动则过亿数据的复杂统计,如果能合理使用持久化,会获取非常不错的性能提升

结束

至此 RDD 持久化就结束了,如有问题,欢迎评论区提问。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流月up

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值