天天看点

Learning Spark笔记6-使用key,value

使用Key/Value

Key/Value是Spark中许多操作的常见数据类型。Key/Value RDD通常用于执行聚合,通常我们做一些ETL工作(extract,transform,load)将数据转换为Key/Value格式。Key/Value RDD的操作(例如,计数每个产品的评论,将相同键的数据分在一起,然后将两个不同的RDDs分组在一起)

Spark还提供一个高级功能,可以让用户控制跨节点的RDD布局:分区。使用可控分区,被访问的数据集中在相同的节点上可以极大地减少应用程序通讯的成本。我们会使用PageRank算法说明分区。为分布式数据集选择正确的分区类似于为本地选择正确的数据结构。

1.动机

Spark为包含key/value的RDDs提供特殊的操作。这些RDDs被称为pair RDDs。它提供并行方式操作每个key,或者将网络上的数据重新分组。例如,reduceByKey()可以分别的对每个key聚合数据,join()可以通过相同的键分组元素合并两个RDDs。通常是提取(时间、客户ID或其他标识),使用这些字段作为pair RDD操作中的key。

2.创建Pair RDDs

一种情况是直接由key/value数据返回pair RDDs,另一种情况是我们有一个规则的RDD,然后将它转换成pair RDD。我们可以使用map()来返回key/value。下面的例子,我们使用文本的RDD,每行的第一个单词是key。

Example 4-1. Creating a pair RDD using the first word as the key in Python

pairs = lines.map(lambda x: (x.split(" ")[0], x))

Example 4-2. Creating a pair RDD using the first word as the key in Scala

val pairs = lines.map(x => (x.split(" ")(0), x))

Java没有tuple类型,所以Spark Java API提供了scala.Tuple2类。这个类很简单,Java用户可以使用new Tuple2(elem1,elem2)构造一个新的tuple,使用._1()和._2()访问他们。

Example 4-3. Creating a pair RDD using the first word as the key in Java

PairFunction<String, String, String> keyData =

 new PairFunction<String, String, String>() {

 public Tuple2<String, String> call(String x) {

 return new Tuple2(x.split(" ")[0], x);

 }

};

JavaPairRDD<String, String> pairs = lines.mapToPair(keyData);

从内存的集合中创建pair RDD,Scala和Python是使用SparkContext.parallelize() ,Java是使用SparkContext.parallelizePairs()

3.Pair RDDs的转换

Pair RDDs也是RDDs,因此支持与RDDs相同的功能。接着之前的例子,我们可以排除超过20个字母的行

Example 4-4. Simple filter on second element in Python

result = pairs.filter(lambda keyValue: len(keyValue[1]) < 20)

Example 4-5. Simple filter on second element in Scala

pairs.filter{case (key, value) => value.length < 20}

Function<Tuple2<String, String>, Boolean> longWordFilter =

 new Function<Tuple2<String, String>, Boolean>() {

 public Boolean call(Tuple2<String, String> keyValue) {

 return (keyValue._2().length() < 20);

 }

 };

JavaPairRDD<String, String> result = pairs.filter(longWordFilter);

有时我们只想访问pair RDD的值,Spark提供了mapValues(func),它与map{case(x,y):(x,func(y))}相同

继续阅读