序言
Spark 是当前比较热门的大数据计算平台,常见与 Hadoop 的 Yarn 以及 HDFS 结合来完成大数据计算任务。
Spark 相比传统的 MapReduce 模式,有如下优势:
- 大量适用于分布式计算的 operation;MapReduce 确实经典,不过相对繁琐
- 提供了 memory cache(号称加速读取100倍);显然 cache 对 迭代算法 iterative 非常有利。
- 深度地支持更多语言:Java、scala、python、R(当然,scala 是直接编译字节码运行在 Java virual Machine 上,效率明显高于其他);MapReduce 则是通过 Hadoop Streaming 这种间接方式支持的。
- 酷炫的 spark-shell,interactive 式地开发或查看数据
本文集合我对 Spark 理解、经验,来整体介绍一下 Spark。
1. Spark 架构
个人倾向于区分出物理架构以及运行时架构。物理架构是 Spark 集群本身的构成描述。而Runtime 架构是 Application 具体执行时的集群动态生成、分配的执行单元架构。此外,还有 Application 任务具体分解的结构(任务必须能被很平均地分解才能充分发挥集群计算的性能,所以很重要)。
1.1 物理架构
物理结构描述了 Spark 集群的物理构成。
Figure 1. Physical Structure of Spark
1.1.1 Driver Program(Client)
本地启动程序。我们提交 spark-submit 或者 启动 spark-shell 的时候就是创建了一个 driver 用于执行 Application。
Driver 负责创建并持续维护本地基本执行环境 SparkContext(1.2中详解)、HiveContext 等,并通过我们配置的参数来访问集群。Driver 会和 Cluster Manager 提交任务,申请执行资源;之后与 Worker 上的 执行单元 Executor(1.2中详解,相当于申请到的计算机资源)进行交互,持续发布具体任务(切分好的 Task)、跟踪执行、获取结果。
1.1.2 Cluster Manager
集群管理节点。管理内容包含 内存、CPU 等资源划分以及 任务提交队列 的管理;例如通常是通过一个FIFO队列来管理大家的 spark 任务提交,分配有限的资源。当任务需要的资源准备就绪,Cluster Mnager 就会告知 Driver 具体的资源细节(比如那个机器那个端口),之后 Driver 就可以直接与 Worker 通信,推送代码并开始跑任务。
集群常见的部署方式可以是基于 Yarn 或者 Standlone;前者为 Hadoop 平台通用的资源管理框架,后者为 Spark 直接负责管理集群资源。另外,集群底层的分布式文件存储一般使用 hdfs。而 Spark 集群本身专注于 分布式计算,搞定自己的核心任务就好。
1.1.3 Worker Node
集群执行节点。一个真正的物理节点可以虚拟出多个 Worker,其负责执行真正的运算。Worker 由 Cluster Manager 管理,任务执行时由 Worker 上会创建 Executor(也被称为 Container 容器) 进程实例执行具体代码。Worker 负责管理、监控其创建的 Executor,必要的时候可以直接 kill 掉。
注意,Worker 只对 Cluster manager 负责,不与用户侧 Driver 交互。而 Worker 运行时创建的 Eexcutor 与 Driver 直接交互。
1.2 Runtime 架构
Runtime 结构指的是 Spark 具体执行 Application 时,在集群上动态创建出来的执行体的结构;包括 Driver 上的 SparkContext 和 参与执行的 Worker 上的 Executor。他们的生命周期都贯穿整个 Application。
Figure 2. Runtime Structure of Spark
1.2.1 SparkContext
由 Driver 创建、维护的 SparkContext,用于与整个集群的 Executor 进行直接交互。它可以直接创建 RDD、广播共享变量等等,具体包含了 RDD Graph、DAGScheduler、TaskScheduler等模块。这里面包含着很多重要的元数据,例如各个 RDD 之间的关联信息,所以集群数据丢失时可以精确到 partition 地自动地高效地恢复丢失数据;以及 Hive 表的 schema 信息等。
这里引出了一个潜在瓶颈:由于 SparkContext 职责重大,对于数据进行着 partition 粒度的精确追踪记录;当数据量过大时,SparkContext 本身可能会卡死。
1.2.2 Executor
Executor 是由 Worker 创建的具体执行单元,拥有独立的 JVM 进程,又被称为容器 Container,在一个隔离独立的环境中执行 Task。Executor 在初始化时会载入所执行 jar 包以及相关依赖。
Execu