《Spark快速大数据分析》
【RDD】
不可变的分布式对象集合。
Spark使用谱系图(lineage graph)来记录不同 RDD 之间的依赖关系。
每当我们调用一个新的行动操作时,整个 RDD 都会从头开始计算。要避 免这种低效的行为,用户可以将中间结果持久化。
【惰性求值】
惰性计算RDD:Spark 了解完整的转化操作链,只计算求结果时真正需要的数据。在被调用行动操作之前 Spark 不会 开始计算。
当我们调用 sc.textFile() 时,数据并没有读取进来,而是在必要时才会读取。Spark 使用惰性求值,这样就可以把一些操作合并到一起来减少计算数据的步骤。
【向Spark传递函数】
def getMatchesFieldReference(rdd: RDD[String]): RDD[String] = {
// 问题:"query"表示"this.query",因此我们要传递整个"this" rdd.map(x => x.split(query))
}
def getMatchesNoReference(rdd: RDD[String]): RDD[String] = {
// 安全:只把我们需要的字段拿出来放入局部变量中 val query_ = this.query
rdd.map(x => x.split(query_))
}
【笛卡儿积】
cartesian(other) 转化操作会返回 所有可能的 (a, b) 对
【持久化(缓存)】
【pair RDD】
val pairs = lines.map(x => (x.split(" ")(0), x))
【数据分区】
和单节点的程序需要为记录集合选择合适的数据结构一样,Spark 程序可以通过控制 RDD 分区方式来减少通信开销。
Scala 自定义分区方式
val userData = sc.sequenceFile[UserID, UserInfo]("hdfs://...").partitionBy(new HashPartitioner(100)).persist() // 构造100个分区
100 表示分区数目,它会控制之后对这个 RDD 进行进一步操作(比如连接操作)时有多少任务会并行执行。总的来说,这个值至少应该和集群中的总核心数一样。
如果没有将 partitionBy() 转化操作的结果持久化,那么后面每次用到这个 RDD 时都会重复地对数据进行分区操作。不进行持久化会导致整个 RDD 谱系图重新求值。那样的话,partitionBy() 带来的好处就会被抵消,导致重 复对数据进行分区以及跨节点的混洗,和没有指定分区方式时发生的情况十分相似。
Spark 的许多操作都引入了将数据根据键跨节点进行混洗的过程。所有这些操作都会 从数据分区中获益。就 Spark 1.0 而言,能够从数据分区中获益的操作有 cogroup()、 groupWith()、join()、leftOuterJoin()、rightOuterJoin()、groupByKey()、reduceByKey()、 combineByKey() 以及 lookup()。
为了最大化分区相关优化的潜在作用,你应该在无需改变元素的键时尽量使 用 mapValues() 或 flatMapValues()。
【数据读取和保存】
Spark SQL中的结构化数据:Apache Hive 是 Hadoop 上的一种常见的结构化数据源。
【共享变量】
累加器 & 广播变量
累加器,提供了将工作节点中的值聚合到驱动器程序中的简单语法。 累加器的一个常见用途是在调试时对作业执行过程中的事件进行计数。
通 过 在 驱 动 器 中 调 用 SparkContext.accumulator(initialValue) 方 法, 创 建 出 存 有 初 始值的累加器。返回值为 org.apache.spark.Accumulator[T] 对象,其中 T 是初始值 initialValue 的类型。
工作节点上的任务不能访问累加器的值。

浙公网安备 33010602011771号