泰安市网站建设_网站建设公司_CSS_seo优化
2026/1/17 17:22:56 网站建设 项目流程

今天的学习目标聚焦解决重复计算的性能问题(RDD 持久化),并摆脱交互式 Shell,完成独立 Spark 应用程序的开发、打包与运行,这也是从 “零散操作” 到 “工程化开发” 的关键一步。
昨天在 Shell 中操作时发现一个问题:如果对同一个 RDD 多次执行行动操作,Spark 会重复从头计算这个 RDD 的所有依赖链。比如对处理后的单词 RDD 既执行collect()又执行saveAsTextFile(),两次行动操作会触发两次完整的计算流程,数据量小的时候没感觉,但数据量大时会严重拖慢速度。
今天重点学习的RDD 持久化就是解决这个问题的核心方案:通过cache()或persist()方法,将 RDD 的数据存储在内存中,后续操作直接读取缓存数据,无需重复计算。

  1. 持久化的核心用法
    先明确两个方法的区别:
    cache():简化版的persist(),默认将 RDD 持久化到内存(对应存储级别MEMORY_ONLY)。
    persist():可以指定存储级别,比如MEMORY_AND_DISK(内存存不下时写入磁盘)、DISK_ONLY(仅存磁盘)等,更灵活。
  2. 实操验证性能差异
    我在 Spark Shell 中做了一组对比测试,用一个稍大的数据集(生成 100 万条随机数的 RDD
    // 1. 不使用持久化,两次行动操作
    val rdd = sc.parallelize(1 to 1000000).map(_ => scala.util.Random.nextInt(1000))
    // 第一次count(触发完整计算)
    val start1 = System.currentTimeMillis()
    rdd.count()
    val end1 = System.currentTimeMillis()
    println(s"第一次count耗时:${end1 - start1}ms") // 输出约120ms

// 第二次count(重复计算)
val start2 = System.currentTimeMillis()
rdd.count()
val end2 = System.currentTimeMillis()
println(s"第二次count耗时:${end2 - start2}ms") // 输出约115ms

// 2. 使用持久化,两次行动操作
val rddCache = sc.parallelize(1 to 1000000).map(_ => scala.util.Random.nextInt(1000))
rddCache.cache() // 缓存RDD

// 第一次count(触发计算并缓存)
val start3 = System.currentTimeMillis()
rddCache.count()
val end3 = System.currentTimeMillis()
println(s"缓存后第一次count耗时:${end3 - start3}ms") // 输出约125ms(略长,因为要缓存)

// 第二次count(读取缓存)
val start4 = System.currentTimeMillis()
rddCache.count()
val end4 = System.currentTimeMillis()
println(s"缓存后第二次count耗时:${end4 - start4}ms")
测试结果很直观:未缓存时两次计算耗时几乎一致,缓存后第二次计算耗时仅为第一次的 1/8,这就是持久化的核心价值。同时也注意到,缓存后的第一次计算会略慢,因为需要额外的时间将数据写入内存,这是新手容易忽略的点。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询