One
首先,我阅读一条推文,并通过映射解析成推文案例类,parseTweet
解析为我的解析函数:
val tweets = sc.textFile("/home/gakuo/Documents/bigdata/NintendoTweets").map(parseTweet)
二
然后我使用一个函数来配对RDD,通过toPairRdd内部的映射(hashtags, likes)
生成一对RDD:
val pairedRDD = toPairRdd(tweets).persist()
问题
在阅读了上面(一(中的RDD后,将其保留为(二(中的转换是否有帮助?我在想,既然都是懒惰的,那么坚持其实就是浪费记忆。
三
计算完pairRDD后,我想计算每个主题标签的分数:toScores
使用reduceByKey
val scores = toScores(pairedRDD).persist()
问题
我使用reduceByKey
.这种对RDD方法是否会导致洗牌?我读过一篇论文,其中指出:
"当生成的RDD依赖于来自同一RDD或另一个RDD的其他元素时,可能会发生洗牌。 cogroup, groupWith, join, leftOuterJoin, rightOuterJoin, groupByKey, reduceByKey, combineByKey, distinct, intersection, 重新分区,合并导致洗牌。为了避免这些类型的操作的随机排序,请确保转换遵循与原始RDD相同的分区">
同一篇论文还指出,reduceByKey
遵循与原始RDD相同的分区。
当你有许多操作总是再次执行相同转换的数量时,使用 persist(在内存/磁盘/两者上(是有问题的。如果一次又一次地重新计算需要太长时间。
在您的情况下,不需要持久或缓存,因为它是一次性过程。您需要知道,阶段是在洗牌之前将尽可能多的转换放在一起的。你在这里会有 2 个。
如果要使用配对RDD处理其他一些数据需求,则建议持久化。
无论如何,这些行动都更相关。
如果您有多个操作使用相同的 rdd,那么建议坚持。到目前为止,我还没有在您的代码中看到任何操作。所以我看不出有任何理由缓存rdd。持久/缓存也延迟计算。
持久/缓存 - 不保证数据将在执行的生命周期内保留,因为持久遵循 LRU 最近最少使用的算法,如果内存已满,该算法可能会根据最少使用的 rdd 刷新数据。使用持久时需要牢记的所有事情。
Reducebykey - 这是一个广泛的转变,因为可能会发生随机播放。但首先,它确实首先在分区内合并了带有键的数据,然后执行reduce操作。所以成本更低。始终避免使用groupbykey,因为它直接打乱数据,而不将数据与分区中的键组合在一起。编码时请避免按组键。