本节书摘来自华章出版社《spark大数据分析:核心概念、技术及实践》一书中的第3章,第3.1节,作者[美] 穆罕默德·古勒(mohammed guller),更多章节内容可以访问云栖社区“华章计算机”公众号查看。
3.3 应用运行
本节主要描述数据处理代码是怎么在spark集群中执行的。
3.3.1 术语
先来看看几个术语的定义。
shuffle操作。shuffle操作是指在集群节点上对数据进行重新分配。这是一个耗时操作,因为它涉及在网络间传输数据。需要注意的是,shuffle操作不是对数据进行随机重新分配,它按照某些标准将数据分成不同的集合。每一个集合就是一个新的分区。
作业。作业是一系列计算的集合,spark执行这些计算并将结果返回给驱动程序。作业本质上就是在spark集群上运行数据处理算法。一个应用程序可以发起多个作业。本章稍后将会介绍作业是怎么执行的。
阶段。一个阶段由若干个任务构成。spark将一个作业分解为一个由若干个阶段构成的dag,每一个阶段依赖于其他阶段。举个例子,把一个作业分解为阶段0和阶段1两个阶段。只有当阶段0完成之后,才可以开始阶段1。spark利用shuffle边界将任务分成不同的阶段。不要求shuffle操作的任务属于同一阶段。只有在开始一个新阶段时,任务才需要输入数据是经过shuffle操作的。
3.3.2 应用运行过程
有了上面的这些定义,我们就可以描述一个spark应用在集群节点上并行处理数据的过程。当一个spark应用开始运行的时候,spark会连接集群管理员,获取在worker节点上的执行者资源。就像前面所说的,spark应用把一个数据处理算法当成一个作业提交。spark将这个作业分解成由若干个阶段构成的dag。然后,spark在执行者上调度这些阶段的运行,调度操作由集群管理员提供的底层调度器实现。执行者并行地运行spark提交的任务。
每一个spark应用都有一组其自己的位于worker节点上的执行者。这样的设计有诸多好处。首先,不同应用中的任务由于运行在不同jvm之上,使得它们之间互相隔离。一个应用程序中的错误任务并不会让其他应用崩溃。其次,调度任务变得轻而易举。spark一次只需要调度归属于同一应用的任务。它不用处理这样一种复杂情况,其中调度的多个任务属于多个并发执行的不同应用。
然而,这种设计也有不足之处。由于不同应用在不同的jvm进程中运行,因此它们之间就不太方便共享数据。即使它们可能在同一个worker节点上运行,它们也只能通过读写磁盘的方式共享数据。就像前面所说的,读写磁盘是耗时的操作。因此,应用间通过磁盘共享数据,将会遇到性能问题。