Coursera 笔记

Module 03 · Apache Spark

Parallel Programming using Resilient Distributed Datasets并行编程与弹性分布式数据集(RDD)

Coursera ↗

欢迎观看《并行编程与弹性分布式数据集》视频!在观看完该视频后,您将能够:

  • 定义弹性分布式数据集(RDD)
  • 定义并行编程
  • 解释 Apache Spark 中的弹性特性
  • 将 RDD 和并行编程与 Apache Spark 联系起来

弹性分布式数据集(RDD)

弹性分布式数据集(Resilient Distributed Dataset,简称 RDD)是 Spark 的主要数据抽象。RDD 是一组容错的元素,分布在集群的各个节点上,能够接收并行操作。

RDD 的特性

  • 容错性:RDD 是容错的,意味着即使集群中的某些节点失败,数据依然能够恢复。
  • 不可变性:RDD 一旦创建,就不能被修改。每个操作都会生成一个新的 RDD,而不是改变原有的 RDD。
  • 支持多种数据格式:RDD 支持文本文件、序列文件、Avro、Parquet 和 Hadoop 输入格式,还支持本地文件、Cassandra、HBase、HDFS、Amazon S3 等文件格式,以及多种关系型和 NoSQL 数据库。

创建 RDD

有三种方法可以创建 RDD:

  1. 使用外部文件:通过 Hadoop 支持的文件系统(如 HDFS、Cassandra、HBase 或 Amazon S3)加载外部文件。
  2. 使用 parallelize 函数:将现有的集合应用于 driver 程序中的 parallelize 函数。这可以在 Python、Java 或 Scala 等高阶 API 中进行。
  • 例如,使用 Scala 或 Python 创建一个简单的 RDD。
  • 代码片段展示了如何从现有集合(如列表)创建 RDD。
  1. 应用转换操作:在现有 RDD 上应用转换操作,从而创建一个新的 RDD。

RDD 和分区

当使用 parallelize 函数时,必须指定分区数,通常每个 CPU 使用 2 到 4 个分区。Spark 会自动根据集群大小设置分区数,当然,你也可以手动指定分区数。

并行编程

并行编程是同时使用多个计算资源来解决计算任务。并行编程将任务分解为独立的部分,并使用多个处理器同时解决这些任务。每个处理器访问共享的内存池,并配备控制和协调机制。

RDD 与并行编程

在 Spark 中,创建 RDD 就是将一个数组的对象或一个数据集分割成多个分区,然后将这些分区分配到各个节点上。每个节点负责一个分区,并行执行任务。这使得 RDD 可以本质上支持并行操作。

RDD 在 Spark 中的弹性特性

RDD 的弹性通过不可变性和缓存机制来实现:

  1. 不可变性:由于 RDD 是不可变的,数据一旦创建,就无法修改,因此具有很强的恢复能力。
  2. 缓存机制:RDD 可以将数据集保存在内存中,跨多个操作进行持久化。这种缓存是容错的,始终可以恢复,因为 RDD 是不可变的,并且 Hadoop 数据源本身也具有容错能力。
  • 当持久化 RDD 时,每个节点会将计算出来的分区存储在内存中,并在后续的操作中重用相同的分区。这可以显著提高后续操作的速度,通常比不缓存的操作快 10 倍以上。
  • 持久化是迭代算法和快速交互式应用的关键工具。

总结

在本视频中,您学到了:

  • 可以通过外部或本地文件、集合或另一个 RDD 创建 RDD。
  • RDD 是不可变的,始终可以恢复。
  • 并行编程是同时使用多个计算资源来解决计算任务。
  • RDD 可以在内存中持久化或缓存数据集,显著加速迭代操作。

一、RDD(弹性分布式数据集)的本质

RDD是Spark的​​核心数据抽象​​,代表一个不可变、可分区的分布式对象集合。

  • ​​关键特性​​:
    1. ​​Resilient(弹性)​​:支持容错(通过血缘关系+数据重建机制)。
    2. ​​Distributed(分布式)​​:数据自动分片(Partition)并在集群节点间分布。
    3. ​​Dataset(数据集)​​:支持多种数据源(HDFS、S3、数据库等)。
  • ​​架构意义​​:RDD是Spark实现​​数据并行​​和​​计算并行​​的基石,抽象了分布式计算的复杂性。

二、RDD的创建方式(与架构设计关联)

  1. ​​从外部数据源创建​​(如HDFS、S3):
  • 数据自动分区,分区数影响并行度(默认按块大小或配置决定)。
  • ​​架构启示​​:支持异构数据源集成,扩展性强。
  1. ​​并行化现有集合​​(parallelize):
  • 将本地集合(如List)转换为分布式RDD,可手动指定分区数(如sc.parallelize(data, 4))。
  • ​​分区策略​​:每个分区对应一个并行任务(Task),分区数决定并行粒度。
  • ​​最佳实践​​:通常为每个CPU核心设置2-4个分区,避免资源空闲或调度开销。
  1. ​​通过转换操作生成新RDD​​(如map、filter):
  • RDD不可变(Immutable),任何转换都生成新RDD,形成​​血缘关系(Lineage)​​。
  • ​​容错基础​​:血缘记录转换步骤,故障时可重新计算丢失的分区。

三、并行编程在Spark中的实现

  • ​​并行本质​​:
    • Spark将RDD数据分片(Partition)分布到集群节点,每个分区独立处理(无共享状态)。
    • ​​任务并行​​:每个分区对应一个Task,由Executor并行执行(如右图所示)。
  • ​​与传统并行的区别​​:
    • 传统多线程:共享内存,需锁/同步机制(易死锁、竞争)。
    • Spark并行:基于数据分区+无状态计算(避免竞争,简化并发设计)。
  • ​​架构优势​​:
    • ​​线性扩展​​:增加节点即可处理更大数据(无需改代码)。
    • ​​隐式并行​​:开发者只需定义转换逻辑(如rdd.map(f)),Spark自动并行化。

四、容错机制(Resilience)的实现原理

  1. ​​血缘关系(Lineage)​​:
  • RDD记录其生成依赖链(如rdd3 = rdd2.map(f)← rdd2 = rdd1.filter(g))。
  • 故障时,仅重新计算丢失的分区(而非全部数据),高效恢复。
  1. ​​持久化(Persist/Cache)​​:
  • 将RDD缓存到内存或磁盘,避免重复计算(尤其迭代算法如机器学习)。
  • ​​容错性​​:即使缓存数据丢失,仍可通过血缘重新计算。
  • ​​性能提升​​:缓存后后续操作加速10倍以上(减少I/O和计算开销)。
  1. ​​数据源容错​​:
  • 若数据来自HDFS等可靠存储,可直接从源重新读取。

五、与系统架构设计的关联

  1. ​​分区策略影响性能​​:
  • 过多分区 → 任务调度开销大;过少分区 → 资源利用不足。
  • 需根据数据大小、集群资源动态调整(如repartition操作)。
  1. ​​缓存策略选择​​:
  • 内存充足时优先缓存到内存(MEMORY_ONLY),否则序列化或落盘(权衡速度与资源)。
  1. ​​容错与一致性​​:
  • RDD的不可变性+血缘机制提供​​最终一致性​​,适合批处理场景(非实时事务)。
  1. ​​扩展性设计​​:
  • RDD模型天然支持横向扩展(增加节点),符合分布式系统设计原则。

六、备考重点总结

概念 架构意义 应用场景
RDD不可变性 简化并发设计,支持容错和重现计算 迭代算法(如机器学习训练)
数据分区 决定并行粒度,影响负载均衡和资源利用率 大数据ETL、分布式计算
血缘关系 轻量级容错机制,替代数据复制的高开销 故障恢复、计算优化
持久化 性能优化关键,减少重复计算和I开销 迭代查询、交互式分析

​​核心思想​​:RDD通过​​数据分区+转换血缘​​抽象了分布式计算的并行性和容错性,让开发者聚焦业务逻辑而非底层分布式细节。作为架构师,需理解分区策略、缓存机制和容错原理,以设计高效、可扩展的大数据系统。