【Spark】Spark容错机制

引入

通常来讲,分布式数据集的容错性有两种方式:数据检查点和记录数据的更新
面向大规模数据分析,数据检查点操做成本很是高,需要经过数据中心的网络链接在机器之间复制庞大的数据集,而网络带宽每每比内存带宽低得多,同一时候还需要消耗不少其它的存储资源。git


所以,Spark选择记录更新的方式。但是,假设更新粒度太细太多,那么记录更新成本也不低。所以。RDD仅仅支持粗粒度转换,即仅仅记录单个块上运行的单个操做,而后将建立RDD的一系列变换序列(每个RDD都包括了他是怎样由其它RDD变换过来的以及怎样重建某一块数据的信息。所以RDD的容错机制又称“血统(Lineage)”容错)记录下来,以便恢复丢失的分区。
Lineage本质上很是类似于数据库中的重作日志(Redo Log),仅仅只是这个重作日志粒度很是大,是对全局数据作相同的重作进而恢复数据。github

Lineage机制

Lineage简单介绍

相比其它系统的细颗粒度的内存数据更新级别的备份或者LOG机制,RDD的Lineage记录的是粗颗粒度的特定数据Transformation操做(如filter、map、join等)行为。数据库

当这个RDD的部分分区数据丢失时,它可以经过Lineage获取足够的信息来又一次运算和恢复丢失的数据分区。因为这样的粗颗粒的数据模型,限制了Spark的运用场合,因此Spark并不适用于所有高性能要求的场景,但同一时候相比细颗粒度的数据模型,也带来了性能的提高。缓存

两种依赖关系

RDD在Lineage依赖方面分为两种:窄依赖(Narrow Dependencies)与宽依赖(Wide Dependencies,源代码中称为Shuffle
Dependencies),用来解决数据容错的高效性。 markdown

  • 窄依赖是指父RDD的每个分区最多被一个子RDD的分区所用,表现为一个父RDD的分区相应于一个子RDD的分区
    或多个父RDD的分区相应于一个子RDD的分区,也就是说一个父RDD的一个分区不可能相应一个子RDD的多个分区。
    1个父RDD分区相应1个子RDD分区,这当中又分两种状况:1个子RDD分区相应1个父RDD分区(如map、filter等算子),1个子RDD分区相应N个父RDD分区(如co-paritioned(协同划分)过的Join)。
  • 宽依赖是指子RDD的分区依赖于父RDD的多个分区或所有分区,即存在一个父RDD的一个分区相应一个子RDD的多个分区。
    1个父RDD分区相应多个子RDD分区,这当中又分两种状况:1个父RDD相应所有子RDD分区(未经协同划分的Join)或者1个父RDD相应非所有的多个RDD分区(如groupByKey)。

本质理解:依据父RDD分区是相应1个仍是多个子RDD分区来区分窄依赖(父分区相应一个子分区)和宽依赖(父分区相应多个子分
区)。假设相应多个,则当容错重算分区时,因为父分区数据仅仅有一部分是需要重算子分区的,其他数据重算就形成了冗余计算。网络

对于宽依赖。Stage计算的输入和输出在不一样的节点上,对于输入节点完善。而输出节点死机的状况。经过又一次计算恢复数据这样的状况下,这样的方法容错是有效的,不然无效。因为没法重试,需要向上追溯其祖先看可否够重试(这就是lineage,血统的意思),窄依赖对于数据的重算开销要远小于宽依赖的数据重算开销。框架

窄依赖和宽依赖的概念主要用在两个地方:一个是容错中至关于Redo日志的功能;还有一个是在调度中构建DAG做为不一样Stage的划分点。分布式

依赖关系的特性

第一,窄依赖可以在某个计算节点上直接经过计算父RDD的某块数据计算获得子RDD相应的某块数据;宽依赖则要等到父RDD所有数据都计算完毕以后,而且父RDD的计算结果进行hash并传到相应节点上以后才干计算子RDD。
第二,数据丢失时,对于窄依赖仅仅需要又一次计算丢失的那一块数据来恢复。对于宽依赖则要将祖先RDD中的所有数据块所有又一次计算来恢复。因此在长“血统”链特别是有宽依赖的时候,需要在适当的时机设置数据检查点。ide

也是这两个特性要求对于不一样依赖关系要採取不一样的任务调度机制和容错恢复机制。post

容错原理

在容错机制中,假设一个节点死机了。而且运算窄依赖。则仅仅要把丢失的父RDD分区重算就能够,不依赖于其它节点。而宽依赖需要父RDD的所有分区都存在,重算就很是昂贵了。

可以这样理解开销的经济与否:在窄依赖中。在子RDD的分区丢失、重算父RDD分区时,父RDD相应分区的所有数据都是子RDD分区的数据,并不存在冗余计算。

在宽依赖状况下,丢失一个子RDD分区重算的每个父RDD的每个分区的所有数据并不是都给丢失的子RDD分区用的,会有一部分数据至关于相应的是未丢失的子RDD分区中需要的数据,这样就会产生冗余计算开销,这也是宽依赖开销更大的缘由。所以假设使用Checkpoint算子来作检查点,不只要考虑Lineage是否足够长,也要考虑是否有宽依赖,对宽依赖加Checkpoint是最物有所值的。

Checkpoint机制

经过上述分析可以看出在下面两种状况下,RDD需要加检查点。

  1. DAG中的Lineage过长,假设重算,则开销太大(如在PageRank中)。
  2. 在宽依赖上作Checkpoint得到的收益更大。

因为RDD是仅仅读的,因此Spark的RDD计算中一致性不是主要关心的内容,内存相对easy管理,这也是设计者很是有远见的地方,这样下降了框架的复杂性,提高了性能和可扩展性,为之后上层框架的丰富奠基了强有力的基础。


在RDD计算中。经过检查点机制进行容错,传统作检查点有两种方式:经过冗余数据和日志记录更新操做。

在RDD中的doCheckPoint方法至关于经过冗余数据来缓存数据。而以前介绍的血统就是经过至关粗粒度的记录更新操做来实现容错的。

检查点(本质是经过将RDD写入Disk作检查点)是为了经过lineage作容错的辅助。lineage过长会形成容错成本太高。这样就不如在中间阶段作检查点容错,假设以后有节点出现故障而丢失分区。从作检查点的RDD開始重作Lineage,就会下降开销。

转载请注明做者Jason Ding及其出处
GitCafe博客主页(http://jasonding1354.gitcafe.io/)
Github博客主页(http://jasonding1354.github.io/)
CSDN博客(http://blog.csdn.net/jasonding1354)
简书主页(http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)
Google搜索jasonding1354进入个人博客主页

相关文章
相关标签/搜索