Spark Streaming之容错&高可用

46 篇文章 3 订阅
41 篇文章 1 订阅
本文探讨了Spark Streaming的容错机制,包括RDD的血缘关系、接收数据和转换数据的语义,以及如何处理工作节点和驱动程序节点的故障。文章还讨论了不同输入源的容错保证,如文件、可靠与不可靠的接收器,以及Kafka Direct API。最后,分析了输出操作的至少一次语义,提出了实现精确一次语义的方法。
摘要由CSDN通过智能技术生成

一.背景

Spark的RDD的基本容错语义:

  1. RDD是一个不变的,确定性可重新计算的分布式数据集。每个RDD都会记住在容错输入数据集上用于创建它的确定性操作的血缘关系。
  2. 如果由于工作节点故障而导致RDD的任何分区丢失,则可以使用操作血缘关系从原始的容错数据集中重新计算该分区。
  3. 假设所有RDD转换都是确定性的,则最终转换后的RDD中的数据将始终相同,而不管Spark集群中的故障如何。

Spark在容错文件系统【例如HDFS或S3】中的数据上运行。因此,从容错数据生成的所有RDD也是容错的。但是,Spark Streaming并非如此,因为大多数情况下是通过网络接收数据的【fileStream除外】。为了对所有生成的RDD实现相同的容错属性,将接收到的数据复制到集群中工作节点中的多个Spark执行程序中【默认复制因子为2】。这导致系统中发生故障时需要恢复的两种数据:
4. 接收和复制的数据:由于该数据的副本存在于其他节点之上,因此该数据在单个工作节点发生故障时仍可幸免。
5. 已接收但尚未进行复制的数据:由于未复制数据,因此恢复此数据的唯一方法是再次从源中获取数据。

此外,我们应该关注两种故障:

  1. 工作节点的故障:运行执行程序的任何工作节点都可能发生故障,并且这些节点上的所有内存中数据都将丢失。如果有任何接收器在发生故障的节点上运行,那么它们的缓冲数据将丢失。
  2. 驱动程序节点发生故障:如果运行Spark Streaming应用程序的驱动程序节点发生故障,则显然SparkContext会丢失,并且所有执行程序及其内存中的数据也会丢失。

二.定义

流系统的语义通常是根据每个记录可以被系统处理多少次来捕获的。系统在所有可能的操作条件下【尽管有故障等】可以提供三种保证:

  1. 最多一次:每个记录将被处理一次或完全不被处理。
  2. 至少一次:每个记录将被处理一次或多次。它比最多一次强,因为它确保不会丢失任何数据。但是可能会重复处理。
  3. 恰好一次【精确一次】:每个记录将被恰好处理一次,不会丢失任何数据,也不会多次处理任何数据。这显然是三者中最强有力的保证。

三.基本语义

概括地说,在任何流处理系统中,处理数据都需要三个步骤:

  1. 接收数据:使用接收器或其他方式从源接收数据。
  2. 转换数据:使用DStream和RDD转换对接收到的数据进行转换。
  3. 推送数据:将最终转换后的数据推送到外部系统,例如文件系统,数据库,仪表板等。

如果流应用程序必须实现端到端的精确一次保证,那么每个步骤都必须提供精确一次保证。也就是说,每条记录必须被接收一次,被转换一次,并被推送到下游系统一次。让我们在Spark Streaming的上下文中了解这些步骤的语义。

  • 接收数据:不同的输入源提供不同的保证。
  • 转换数据:由于RDD提供的保证,所有接收到的数据将只处理一次。即使出现故障,只要可以访问接收到的输入数据,最终转换后的RDD始终具有相同的内容。
  • 推送数据:默认情况下,输出操作确保至少一次语义,因为它取决于输出操作的类型【是否为幂等】和下游系统的语义【是否支持事务】。但是用户可以实现自己的事务处理机制以实现一次语义。

四.接收数据的语义

不同的输入源提供不同的保证,范围从至少一次到恰好一次。

  • 带文件
    如果所有输入数据已经存在于诸如HDFS之类的容错文件系统中,则Spark Streaming始终可以从任何故障中恢复并处理所有数据。这提供了一次精确的语义,这意味着无论发生什么故障,所有数据都会被精确处理一次。
  • 使用基于接收器的源
    对于基于接收器的输入源,容错语义取决于故障情况和接收器类型。正如前面我们所讨论的,有两种类型的接收器:
    • 可靠的接收器:这些接收器仅在确保已复制接收到的数据后才确认可靠的来源。如果此类接收器发生故障,则源将不会收到对缓冲【未复制】数据的确认。因此,如果重新启动接收器,则源将重新发送数据,并且不会由于失败而丢失任何数据。
    • 不可靠的接收器:此类接收器不发送确认,因此当由于工作程序或驱动程序故障而失败时,可能会丢失数据。
  • 使用Kafka Direct API
    在Spark 1.3中,我们引入了新的Kafka Direct API,可以确保Spark Streaming一次接收所有Kafka数据。同时,如果实施一次精确的输出操作,则可以实现端到端的一次精确保证。

根据所使用的接收器类型,我们可以实现以下语义。如果工作节点发生故障,那么使用可靠的接收器不会造成数据丢失。如果接收器不可靠,则接收到但未复制的数据可能会丢失。如果驱动程序节点发生故障,则除了这些丢失之外,所有已接收并复制到内存中的过去数据都将丢失。这将影响有状态转换的结果。

为了避免丢失过去收到的数据,Spark 1.2引入了预写日志,该日志将收到的数据保存到容错存储中。在启用预写日志和可靠的接收器的情况下,数据丢失为零。就语义而言,它至少提供了一次保证。

下表总结了失败时的语义:
在这里插入图片描述

五.输出操作的语义

输出操作【例如foreachRDD】至少具有一次语义,也就是说,在工作程序失败的情况下,转换后的数据可能多次写入到外部实体。尽管使用saveAs***Files操作将其保存到文件系统是可以接受的【因为文件将被相同的数据简单地覆盖】,但可能需要付出额外的努力才能实现一次语义。有两种方法。

  • 幂等更新:多次尝试总是写入相同的数据。例如,saveAs***Files始终将相同的数据写入生成的文件。
  • 事务性更新:所有更新都是以事务方式进行的,因此原子更新仅进行一次。一种做到这一点的方法如下。
    • 使用批处理时间和RDD的分区索引来创建标识符。该标识符唯一地标识流应用程序中的Blob数据。
    • 使用标识符以事务方式【即原子一次】更新与此Blob的外部系统。也就是说,如果尚未提交标识符,则自动提交分区数据和标识符。否则,如果已经提交,则跳过更新。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值