MapReduce、Drayd包括本文的Spark,都是高级的集群编程模型。前两者都是基于非循环的数据流模型,从物理存储加载;经过DAG的一系列操作,写回到稳定存储。但是这种方式对于迭代式计算、交互式程序效率很低,需要不断地重复读写磁盘。Spark就是针对这种应用方式,提出了一种新的数据模型——RDD(resilient distributed datasets)。

RDD的核心特点是,它存在内存中,且只读,不能被修改。想要修改只能在此基础上创建新的RDD。这种限制使得容错的开销很低。RDD只需要建立依赖关系,就可以通过重新执行一遍路径来恢复。

因此所有的编程都是围绕RDD来进行操作的。如果理解了RDD的意义,剩下的都很好理解。Spark只不过在此基础上提供了大量的操作接口而已。

举一个例子,统计日志中出错的信息。如下所示。

1
2
3
lines = spark.textFile("hdfs://...")
errors = lines.filter(_.startsWith("ERROR"))
errors.cache()

此时,已经有多个RDD产生了:从文件中产生lines;lines经过filter获得errors。此时用户已经可以执行相应的动作。比如

1
errors.count()

甚至更多的动作

1
2
3
4
5
6
7
8
// Count errors mentioning MySQL:
errors.filter(_.contains("MySQL")).count()
// Return the time fields of errors mentioning
// HDFS as an array (assuming time is field
// number 3 in a tab-separated format):
errors.filter(_.contains("HDFS"))
.map(_.split('\t')(3))
.collect()

编程接口

下图基本做了一个总结:

举几个例子:

MapReduce

1
2
3
data.flatMap(myMap)
.groupByKey()
.map((k, vs) => myReduce(k, vs))

WordCount

1
2
3
data.flatmap(_.split(" "))
.map(k => (k, 1))
.reduceByKey((v, v) => v+v)