spark RDD和streaming的容错机制

1. RDD Lineage容错

分布式系统中,常通过副本机制通过数据冗余,来提供高可用性HA。个人认为RDD主要是通过冗余计算的方式来容错的。

RDD并不提供副本机制。

RDD的分布式是指,一个RDD可以切分多个分区(partition),不同的分区可能在集群的不同节点上。
RDD从HDFS读出前,或者写入到HDFS后,通过hadoop.dfs.replication实现数据冗余。

RDD防止数据丢失的机制,是通过"血统重建"(lineage)实现的。spark在计算时,会对RDD应用不同的transformation操作。这一系列操作合并在一起并创建DAG,其中的逻辑执行计划,就构成了RDD的lineage。这个过程中如果丢失了某些RDD,我们可以通过lineage的谱系图来对原始数据重新应用相同的计算,这就是RDD的自我恢复(容错)过程。

如果某个节点在操作过程中崩溃,spark会尝试分配另一个节点该节点在RDD的相同分区上继续处理,进行一系列操作。这样,实际上没有数据丢失。出现故障时需要恢复的两种数据复制类型:
如果数据被复制到了其他节点上,就可以通过计算恢复RDD;
如果没有复制到节点,就通过从源头再次读取它来重新恢复。

RDD的Lineage记录的是粗颗粒度的特定数据Transformation操作(如filter、map、join等)行为。当这个RDD的部分分区数据丢失时,它可以通过Lineage获取足够的信息来重新运算和恢复丢失的数据分区。

Spark的RDD使用日志记录数据集是如何产生的而不是去记录数据本身,使得容错变得高效。不需要数据备份,发生故障时无需从头开始重新启动应用程序。

2. RDD checkpoint容错

spark容错机制

一、窄依赖和宽依赖的概念主要用在两个地方:一个是容错中相当于Redo日志的功能;另一个是在调度中构建DAG作为不同Stage的划分点。某些迭代运算里,DAG中的Lineage过长,如果重算,则开销太大。在最坏的情况下,Spark必须一直返回到原始数据。

二、在宽依赖情况下,丢失一个子RDD分区重算的每个父RDD的每个分区的所有数据并不是都给丢失的子RDD分区用的,会有一部分数据相当于对应的是未丢失的子RDD分区中需要的数据,这样就会产生冗余计算开销,这也是宽依赖开销更大的原因。在窄依赖中,在子RDD的分区丢失、重算父RDD分区时,父RDD相应分区的所有数据都是子RDD分区的数据,并不存在冗余计算。
因此如果使用Checkpoint算子来做检查点,尤其是在宽依赖上做Checkpoint,对于减少容错过程的冗余计算大有裨益。

Checkpoint通过将RDD写入Disk做检查点。Checkpoint是为了对lineage做容错提供辅助,lineage过长会造成容错成本过高,这样就不如在中间阶段做检查点容错,如果之后有节点出现问题而丢失分区,从做检查点的RDD开始重做Lineage,就会减少开销

3. streaming WAL容错

Spark Streaming 是 Spark Core API 的扩展,它支持弹性的,高吞吐的,容错的实时数据流的处理。数据可以通过多种数据源获取,例如 Kafka,Flume,Kinesis 以及 TCP sockets。
基于Receivers的输入源,容错取决于故障情况和Receiver的类型。

故障场景:

  1. Driver故障
    如果正在运行Spark Streaming应用程序的驱动程序节点发生故障,则SparkContent会丢失,所有执行程序都会丢失其内存中数据。
  2. Worker故障
    执行程序的任何工作节点都可能发生故障,从而导致内存丢失。在故障节点上的Receiver,其缓冲区的数据将丢失。

数据源(如 Kafka 和 Flume)允许传输的数据被确认。如果系统从这些可靠的数据来源接收数据,并且被确认(acknowledges)正确地接收数据,它可以确保数据不会因为任何类型的失败而导致数据丢失。有
两种类型的 receivers:

  1. Reliable Receiver(可靠的接收器) - 当数据被接收并存储在 Spark 中并带有备份副本时,一个可靠的接收器(reliable receiver)正确地发送确认(acknowledgment)给一个可靠的数据源(reliable source)。
  2. Unreliable Receiver(不可靠的接收器) - 一个不可靠的接收器(unreliable receiver)不发送确认(acknowledgment)到数据源。这可以用于不支持确认的数据源,或者甚至是可靠的数据源当你不想或者不需要进行复杂的确认的时候。

如果工作程序节点发生故障,并且接收器可靠,则不会丢失任何数据。但是,在Receiver不可靠的情况下,将会发生数据丢失。使用不可靠的Receiver,可能会丢失接收到但未复制的数据。

WAL(write ahead log)
如果驱动程序节点发生故障,则已接收并复制到内存中的所有数据都将丢失。这将影响有状态转换的结果。为了避免数据丢失,Spark 1.2引入了预写日志,该日志将接收到的数据保存到容错存储中。接收到的所有数据都将被写入预写日志,然后才能处理到Spark Streaming。

预写日志的工作方式是:首先将操作意图记录在持久日志中,之后再将操作应用于数据。
如果系统在操作过程中发生故障,则可以恢复丢失的数据。通过读取日志并重新应用其打算执行的数据来完成此操作。

Notes:
可以通过将配置参数 spark.streaming.receiver.writeAheadLog.enable 设置为 true来启用此功能。然而,这些更强的语义可能以单个 receiver 的接收吞吐量为代价。通过 并行运行更多的 receiver 可以纠正这一点,以增加总吞吐量。另外,建议在启用写入日志时,在日志已经存储在复制的存储系统中时,禁用在 Spark 中接收到的数据的复制。这可以通过将输入流的存储级别设置为 StorageLevel.MEMORY_AND_DISK_SER 来完成。

4. streaming checkpoint

streaming 应用程序必须 24*7 运行,因此必须对应用逻辑无关的故障(例如,系统故障,JVM 崩溃等)具有弹性。为了可以这样做,Spark Streaming 需要 checkpoint出足够的信息到容错存储系统,以便可以从故障中恢复。checkpoint 有两种类型的数据。

  1. Metadata checkpointing - 将定义 streaming 计算的信息保存到容错存储(如 HDFS)中。这用于从运行 streaming 应用程序的 driver 的节点的故障中恢复(稍后详细讨论)。
    元数据包括:
    -Configuration - 用于创建流应用程序的配置。
    -DStream operations - 定义 streaming 应用程序的 DStream 操作集。
    -未完成的batches - 批量的job 排队但尚未完成。
  2. Data checkpointing - 将生成的 RDD 保存到可靠的存储。这在一些将多个批次之间的数据进行组合的 状态 变换中是必需的。在这种转换中,生成的 RDD 依赖于先前批次的 RDD,这导致依赖链的长度随时间而增加。为了避免恢复时间的这种无限增加(与依赖关系链成比例),有状态转换的中间 RDD 会定期 checkpoint 到可靠的存储(例如 HDFS)以切断依赖关系链。

总而言之,元数据 checkpoint 主要用于从 driver 故障中恢复,而数据或 RDD checkpoint 对于基本功能(如果使用有状态转换的数据处理失败情况)则是必需的。

spark streaming官方推荐checkpoint定时持久的刷新间隔一般为批处理间隔的5到10倍是比较好的一个方式。Typically, a checkpoint interval of 5 - 10 sliding intervals of a DStream is a good setting to try.

猜你喜欢

转载自blog.csdn.net/rover2002/article/details/106494584