文章目录
一、名词解释
1. RDD
弹性分布式数据集(resilient distributed dataset, 简称RDD)
在Spark中,对数据的所有操作不外乎创建RDD、转化已有RDD以及调用RDD操作进行求值。
二、Spark核心概念
每个
Spark应用都由一个驱动器程序(driver program)来发起集群上的各种并行操作。驱动器程序通过一个SparkContext对象来访问Spark。
三、RDD基础
1. 转化操作和行动操作的区别
转化操作和行动操作的区别在于Spark计算RDD的方式不同。
虽然可以在任何时候定义新的RDD,但Spark只会惰性计算这些RDD。只有他们第一次在一个行动操作中用到时,才会真正计算。
Spark了解了完整的转化操作链之后,就可以只计算求结果时真正需要的数据。
RDD的转化操作是返回一个新的RDD的操作;而行动操作则是向驱动程序返回结果,或把结果写入外部系统的操作,会触发实际的计算。
如果对于一个特定的函数是属于转化操作还是行动操作感到困惑,可以看看它的返回值类型,转化操作返回的是RDD,而行动操作返回的是其他的数据类型。
2. 创建RDD
Spark提供了两种创建RDD的方式:读取外部数据集,以及在驱动程序中对一个集合进行并行化。
3. 转化操作
通过转化操作,从已有的RDD中派生出新的RDD,Spark会使用谱系图来记录这些不同RDD之间的依赖关系。
Spark需要用这些信息来按需计算每个RDD,也可以依靠谱系图,在持久化的RDD丢失部分数据时恢复所丢失的数据。
4. 行动操作
由于行动操作需要生成实际的输出,他们会强制执行那些求值必须用到的RDD的转化操作。
5. 惰性求值
RDD的转化操作都是惰性求值的。这意味着在被调用行动操作之前,Spark不会开始计算。
6. 常见的转化操作
| 序号 | 函数 | 作用 |
|---|---|---|
| 1 | map | 接收一个函数,把这个函数用于RDD中的每个元素,将函数的返回结果作为结果RDD中对应元素的值。 |
| 2 | filter | 接收一个函数,并将RDD中满足该函数的元素放入新的RDD中返回。 |
| 3 | flatMap | 将结果拍平 |
例一:Scala版计算RDD中各值的平方
val input = sc.parallelize(List(1, 2, 3, 4))
val result = input.map(x => x * x)
println(result.collect().mkString(","))

我们可以使用Spark自带的Scala交互式窗口:
# 切换到spark目录
cd spark-3.0.0-bin-hadoop2.7/
# 打开scala版 spark shell
./bin/spark-shell
看到以下输出时,就已经进入spark shell啦
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
Spark context Web UI available at http://*.*.*.*:*
Spark context available as 'sc' (master = local[*], app id = local-1623326674668).
Spark session available as 'spark'.
Welcome to
____ __
/ __/__ ___ _____/ /__
_\ \/ _ \/ _ `/ __/ '_/
/___/ .__/\_,_/_/ /_/\_\ version 3.0.0
/_/
Using Scala version 2.12.10 (OpenJDK 64-Bit Server VM, Java 1.8.0_41)
Type in expressions to have them evaluated.
Type :help for more information.
scala>
我设置了log4j的日志输出级别为ERROR,所以没有INFO或者WARN级别的日志。
设置方式很简单,将
conf/目录下的log4j.properties.template文件,拷贝一份,重命名为log4j.properties,打开log4j.properties,将log4j.rootCategory变量设置为ERROR, console,即可。
例二:Scala中的flatMap()将行数据切分为单词
val lines = sc.parallelize(List("hello world", "hi"))
val words = lines.flatMap(_.split(" "))
words.foreach(println)
7. 常见的行动操作
| 函数名 | 作用 | 示例 |
|---|---|---|
| collect() | 返回RDD中的所有元素 | rdd.collect() |
| count() | RDD中的元素个数 | rdd.count() |
| countByValue() | 各元素在RDD中出现的次数 | rdd.countByValue() |
| take(num) | 从RDD中返回num个元素 | rdd.take(2) |
| top(num) | 从RDD中返回最前面的num个元素 | rdd.top(2) |
| reduce(func) | 并行整合RDD中所有数据 | rdd.reduce((x, y) => x + y) |
| foreach(func) | 对RDD中的每个元素使用给定的函数 | rdd.foreach(println) |
8. 持久化
为了避免多次计算同一个RDD,可以让Spark对数据进行持久化。当我们让Spark持久化存储一个RDD时,计算出RDD的节点会分别保存他们求出的分区数据。
如果一个有持久化数据的节点发生故障,Spark会在需要用到缓存的数据时重算丢失的数据分区。
在Scala和Java中,默认情况下,persist()会把数据以序列化的形式缓存在JVM的堆空间中。
我们在第一次对这个RDD调用行动操作前就调用了persist()方法。persist()调用本身不会触发强制求值。
如果要缓存的数据太多,内存放不下,Spark会自动利用最近最少使用(LRU)的缓存策略把最老的分区从内存中移除。
2115

被折叠的 条评论
为什么被折叠?



