Spark调用集群的计算/存储资源来处理数据,是大规模的数据处理/机器学习绕不开的一个话题。Spark提供获得数据(如RDD and DataFrame)以及数据分析(如MLLib)的工具。我个人主要是在公司里折腾深度学习模型,所以没有用不上MLLib中提供的工具。虽然说看databricks就知道这东西肯定很多人有用的。
RDD和DataFrame恰好是历史上的先后,我们也就照历史线写一下:
Spark RDD
这是wikipedia给出的一个scala RDD示例:
val conf = new SparkConf().setAppName("wiki_test") // create a spark config object
val sc = new SparkContext(conf) // Create a spark context
val data = sc.textFile("/path/to/somedir") // Read files from "somedir" into an RDD of (filename, content) pairs.
val tokens = data.flatMap(_.split(" ")) // Split each file into a list of tokens (words).
val wordFreq = tokens.map((_, 1)).reduceByKey(_ + _) // Add a count of one to each token, then sum the counts per word type.
wordFreq.sortBy(s => -s._2).map(x => (x._2, x._1)).top(10) // Get the top 10 words. Swap word and count to sort by count.
其中data这个参数就是RDD了,这个参数将来会以分布的形式被处理:在这个实例中,可以想见比如好多个核每个去算一些wordFreq,然后再把它们合并起来。这里的思想就是mapReduce,不过Spark RDD这个框架比起最初的mapReduce提供了更灵活的运算机制。
另外一个出现的有趣的点是优化,和所有工具一样,Spark提供了很多的底层的优化。理解这些优化的第一层就是它区分了tranformation和action。transformation产生RDD而只有action会要求得到数据(count, some data or IO of those data);在上面的例子中,只有top要求得到一些数据。实际上所有的tranformation都是lazy evaluation,Spark会看着整个执行计划进行优化,上面的例子中,很容易想见它可以专注于那些count比较高的wordFreq,从而提高整个执行的效率。
Spark DataFrame
从Spark 2.x开始,DataFrame就是主要推荐的Spark处理方式。其主要是提供了一个相比与RDD更抽象而方便的接口:
import org.apache.spark.sql.SparkSession
val url = "jdbc:mysql://yourIP:yourPort/test?user=yourUsername;password=yourPassword" // URL for your database server.
val spark = SparkSession.builder().getOrCreate() // Create a Spark session object
val df = spark
.read
.format("jdbc")
.option("url", url)
.option("dbtable", "people")
.load()
df.printSchema() // Looks at the schema of this DataFrame.
val countsByAge = df.groupBy("age").count() // Counts people by age
上面的例子中df就是dataframe, 它读取了jdbc数据并做了一个count action。这个抽象我觉得真的很方便,因为大家都会接触SQL Table或者pandas dataframe,而Spark就借助了这个很常见的抽象。尽管优化和实现上有很多区别,但是从外部看好像真的没什么区别。