热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

98、SparkStreaming之容错机制以及事务语义详解

Spark Streaming容错机制 要理解Spark Streaming提供的容错机制,先回忆一下Spark RDD的基础容错语义 RDD的基本容错原理.pngRDD,

Spark Streaming容错机制

要理解Spark Streaming提供的容错机制,先回忆一下Spark RDD的基础容错语义

 

13274599-cdca75bf48963db1.png

RDD的基本容错原理.png

  1. RDD,Ressilient Distributed Dataset,是不可变的、确定的、可重新计算的、分布式的数据集。每个RDD都会记住确定好的计算操作的血缘关系,(val lines = sc.textFile(hdfs file); val words = lines.flatMap(); val pairs = words.map(); val wordCounts = pairs.reduceByKey())这些操作应用在一个容错的数据集上来创建RDD。
  2. 如果因为某个Worker节点的失败(挂掉、进程终止、进程内部报错),导致RDD的某个partition数据丢失了,那么那个partition可以通过对原始的容错数据集应用操作血缘,来重新计算出来。
  3. 所有的RDD transformation操作都是确定的,最后一个被转换出来的RDD的数据,一定是不会因为Spark集群的失败而丢失的。

Spark操作的通常是容错文件系统中的数据,比如HDFS。因此,所有通过容错数据生成的RDD也是容错的。然而,对于Spark Streaming来说,这却行不通,因为在大多数情况下,数据都是通过网络接收的(除了使用fileStream数据源)。要让Spark Streaming程序中,所有生成的RDD,都达到与普通Spark程序的RDD,相同的容错性,接收到的数据必须被复制到多个Worker节点上的Executor内存中,默认的复制因子是2。

基于上面说的,在出现失败的事件时,有两种数据需要被恢复:

  1. 数据接收到了,并且已经复制过——这种数据在一个Worker节点挂掉时,是可以继续存活的,因为在其他Worker节点上,还有它的一份副本。
  2. 数据接收到了,但是正在缓存中,等待复制的——因为还没有复制该数据,因此恢复它的唯一办法就是重新从数据源获取一份。

此外,还有两种失败是我们需要考虑的:

  1. Worker节点的失败——任何一个运行了Executor的Worker节点的挂掉,都会导致该节点上所有在内存中的数据都丢失。如果有Receiver运行在该Worker节点上的Executor中,那么缓存的,待复制的数据,都会丢失。
  2. Driver节点的失败——如果运行Spark Streaming应用程序的Driver节点失败了,那么显然SparkContext会丢失,那么该Application的所有Executor的数据都会丢失。

Spark Streaming容错语义的定义

流式计算系统的容错语义,通常是以一条记录能够被处理多少次来衡量的。有三种类型的语义可以提供:

  1. 最多一次:每条记录可能会被处理一次,或者根本就不会被处理。可能有数据丢失。
  2. 至少一次:每条记录会被处理一次或多次,这种语义比最多一次要更强,因为它确保零数据丢失。但是可能会导致记录被重复处理几次。
  3. 一次且仅一次:每条记录只会被处理一次——没有数据会丢失,并且没有数据会处理多次。这是最强的一种容错语义。

Spark Streaming的基础容错语义

在Spark Streaming中,处理数据都有三个步骤:

  1. 接收数据:使用Receiver或其他方式接收数据。
  2. 计算数据:使用DStream的transformation操作对数据进行计算和处理。
  3. 推送数据:最后计算出来的数据会被推送到外部系统,比如文件系统、数据库等。

如果应用程序要求必须有一次且仅一次的语义,那么上述三个步骤都必须提供一次且仅一次的语义。每条数据都得保证,只能接收一次、只能计算一次、只能推送一次。Spark Streaming中实心这些语义的步骤如下:

  1. 接收数据:不同的数据源提供不同的语义保障。
  2. 计算数据:所有接收到的数据一定只会被计算一次,这是基于RDD的基础语义所保障的。即使有失败,只要接收到的数据还是可访问的,最后一个计算出来的数据一定是相同的。
  3. 推送数据:output操作默认能确保至少一次的语义,因为它依赖于output操作的类型,以及底层系统的语义支持(比如是否有事务支持等),但是用户可以实现它们自己的事务机制来确保一次且仅一次的语义。

接收数据的容错语义


  1. 基于文件的数据源
    如果所有的输入数据都在一个容错的文件系统中,比如HDFS,Spark Streaming一定可以从失败进行恢复,并且处理所有数据。这就提供了一次且仅一次的语义,意味着所有的数据只会处理一次。
  2. 基于Receiver的数据源
    对于基于Receiver的数据源,容错语义依赖于失败的场景和Receiver类型。
    可靠的Receiver:这种Receiver会在接收到了数据,并且将数据复制之后,对数据源执行确认操作。如果Receiver在数据接收和复制完成之前,就失败了,那么数据源对于缓存的数据会接收不到确认,此时,当Receiver重启之后,数据源会重新发送数据,没有数据会丢失。

     

    13274599-bebac2adc6bf9779.png

    可靠Receiver的原理.png

     

    不可靠的Receiver:这种Receiver不会发送确认操作,因此当Worker或者Driver节点失败的时候,可能会导致数据丢失。
    不同的Receiver,提供了不同的语义。如果Worker节点失败了,那么使用的是可靠的Receiver的话,没有数据会丢失。使用的是不可靠的Receiver的话,接收到,但是还没复制的数据,可能会丢失。如果Driver节点失败的话,所有过去接收到的,和复制过缓存在内存中的数据,全部会丢失。
    要避免这种过去接收的所有数据都丢失的问题,Spark从1.2版本开始,引入了预写日志机制,可以将Receiver接收到的数据保存到容错存储中。如果使用可靠的Receiver,并且还开启了预写日志机制,那么可以保证数据零丢失。这种情况下,会提供至少一次的保障。(Kafka是可以实现可靠Receiver的)


部署场景Worker失败Driver失败
Spark1.1以前的版本,或者是spark1.2以后的版本,但没有开启预写日志机制1. 不可靠Receiver,会导致缓存数据丢失
2. 可靠的Receiver,可以保证数据零丢失
3. 至少一次的语义
1. 不可靠Receiver,缓存的数据全部丢失
2. 任何Receiver,过去接收的所有数据全部丢失
3. 没有容错语义
Spark 1.2以后版本,并开启了预写日志机制1. 可靠Receiver,零数据丢失
2. 至少一次的语义
1. 可靠Receiver和文件,零数据丢失

从Spark 1.3版本开始,引入了新的Kafka Direct API,可以保证,所有从Kafka接收到的数据,都是一次且仅一次。基于该语义保障,如果自己再实现一次且仅一次语义的output操作,那么就可以获得整个Spark Streaming应用程序的一次且仅一次的语义。

输出数据的容错语义

output操作,比如foreachRDD,可以提供至少一次的语义。那意味着,当Worker节点失败时,转换后的数据可能会被写入外部系统一次或多次。对于写入文件系统来说,这还是可以接收的,因为会覆盖数据。但是要真正获得一次且仅一次的语义,有两个方法:

  1. 幂等更新:多次写操作,都是写相同的数据,例如saveAs系列方法,总是写入相同的数据。
  2. 事务更新:所有的操作都应该做成事务的,从而让写入操作执行一次且仅一次。给每个batch的数据都赋予一个唯一的标识,然后更新的时候判定,如果数据库中还没有该唯一标识,那么就更新,如果有唯一标识,那么就不更新。

dstream.foreachRDD { (rdd, time) =>rdd.foreachPartition { partitionIterator =>val partitionId = TaskContext.get.partitionId()val uniqueId = generateUniqueId(time.milliseconds, partitionId)// partitionId和foreachRDD传入的时间,可以构成一个唯一的标识}
}


推荐阅读
  • 本文介绍了在实现了System.Collections.Generic.IDictionary接口的泛型字典类中如何使用foreach循环来枚举字典中的键值对。同时还讨论了非泛型字典类和泛型字典类在foreach循环中使用的不同类型,以及使用KeyValuePair类型在foreach循环中枚举泛型字典类的优势。阅读本文可以帮助您更好地理解泛型字典类的使用和性能优化。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
  • 本文讨论了在使用Git进行版本控制时,如何提供类似CVS中自动增加版本号的功能。作者介绍了Git中的其他版本表示方式,如git describe命令,并提供了使用这些表示方式来确定文件更新情况的示例。此外,文章还介绍了启用$Id:$功能的方法,并讨论了一些开发者在使用Git时的需求和使用场景。 ... [详细]
  • 渗透测试基础bypass绕过阻挡我们的WAF(下)
    渗透测试基础-bypass ... [详细]
  • Ihaveaforminadirectivetemplate:我在指令模板中有一个表单:<formn ... [详细]
  • vlfilecopy(findfile(vllist>string(10811110311146103105102)))(vll的简单介绍
    本文目录一览:1、一段lisp代码求解释2、运 ... [详细]
  • 作为一个扩展,你需要了解DotNetZip用法,请参见:C#.NET使用第三方类库DotNetZip解压压缩Zip文件你也需要了解单文件内嵌入资源文件基本方法,参见:WPF调用嵌入 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
author-avatar
手机用户2502862657
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有