Apache Spark:缓存和分区

时间:2015-07-06 04:34:41

标签: caching collections apache-spark rdd

这里的情况:我有一个不断增长的数据集合,我希望在整个Hadoop集群中使用RDD进行处理。

这是一个简短的例子:

val elementA = (1, Seq(2, 3))
val elementB = (2, Seq(1, 3))
val elementC = (3, Seq(1, 2))

val testRDD = sc.parallelize(Seq(elementA, elementB, elementC)).
    map(x => (x._1, x._2)).setName("testRDD").cache()

val elementD = (4, Seq(1, 3))
val elementD1 = (1, Seq(4))
val elementD2 = (3, Seq(4))

val testAdd = sc.parallelize(Seq(elementD, elementD1, elementD2)).
    map(x => (x._1, x._2)).setName("testAdd")

val testResult = testRDD.cogroup(testAdd).mapValues(x => (x._1 ++ x._2).flatten)

结果将是这样的(元素的顺序可能会有所不同):

(1, List(2, 3, 4))
(2, List(1, 3))
(3, List(1, 2, 4))
(4, List(1, 3))

这是我的目标:

  1. 我想在群集内存中.cache()我的RDD。
  2. 我希望能够将新元素添加到现有RDD。
  3. 以下是我的想法:

    1. RDD中的每个分区都单独和完全缓存(例如,我有100个元素和4个分区的集合,我称为.cache().collect()cache().first()并且在第一种情况下获得了4个缓存分区,并且在第二种情况)。
    2. testRDD.cogroup(testAdd)的结果是新的RDD,可以再次缓存,如果我们尝试使用var testRDD并致电testRDD = testRDD.cogroup(testAdd),我们就会输掉指向缓存数据的链接。
    3. 我知道,RDD最适合批处理应用程序,我在这里有:每个新元素的Seq()将根据其他元素的属性计算。
    4.   

      有没有办法修改当前的RDD而不从缓存中删除所有的元素?

      我虽然在达到临时存储的某些限制后制作了一种临时存储并将临时存储与当前存储合并...

1 个答案:

答案 0 :(得分:1)

RDD是不可变的,因此您无法向其添加新元素。但是,您可以通过将原始RDD与新元素合并来创建新的RDD,类似于您对testResult RDD所做的操作。

如果要对新RDD使用相同的变量和更新,可以使用var而不是该RDD的val。 e.g。

var testRDD = sc.parallelize(...) val testAdd = sc.parallelize(...) testRDD = testRDD.union(testAdd) testRDD.cache()

这将创建一个连接两个原始RDD的谱系。如果您在testRDD上多次调用union,这可能会导致问题。为了解决这个问题,你可以在testRDD上多次联合后调用checkRD,例如每10个更新一次。您还可以考虑在检查点时调用testRDD上的repartion。

添加到testRDD的所有元素都应使用此技术保留在缓存中。