一起学习Spark(十)结构化流Structured Streaming编程指南(6)-checkpoint失败恢复&查询更改后的语义恢复&连续处理

1.使用检查点(checkpoint)从失败中恢复

在出现故障或有意关闭后,可以使用检查点和写前日志来恢复查询的进度和状态,并从中断的地方继续。我们可以给查询配置一个检查点位置,这样查询会将所有的进度信息(即在每个触发器中处理的偏移范围)和正在运行的聚合(例如之前示例中的word count)保存到检查点的位置。检查点的位置必须是HDFS兼容文件系统中的一个路径,并且可以在启动查询时设置为DataStreamWriter中的一个选项。设置检查点示例:

aggDF
  .writeStream
  .outputMode("complete")
  .option("checkpointLocation", "path/to/HDFS/dir")
  .format("memory")
  .start()

 2.流查询更改后的语义恢复

在从相同检查点位置重新启动之间,允许流查询做哪些更改是有限制的。有几种更改是不允许或无效的。

①“允许”这个术语意味着可以进行指定的更改,但是其效果的语义是否定义良好取决于查询和更改。

②“不允许”这个术语意味着不应该进行指定的更改,因为重新启动的查询可能会失败,并出现不可预知的错误。

详细的更改说明:

1.输入源的数量或类型(即不同的源)的更改:这是不允许的。

2.输入源参数的更改:是否允许这样做以及更改的语义是否定义良好取决于源和查询。例如:

     a)速率限制的添加/删除/更新是允许的,例如将spark.readStream.format("kafka").option("subscribe", "topic") 改为 spark.readStream.format("kafka").option("subscribe", "topic").option("maxOffsetsPerTrigger", ...)

     b)通常不允许更改从kafka中读取数据的topic,因为结果不可预知,例如将spark.readStream.format("kafka").option("subscribe", "topic")更改为 spark.readStream.format("kafka").option("subscribe", "newTopic")

3.输出接收器类型的更改:允许在几个特定接收器组合之间进行更改。例如:

     a)允许文件接收器更改为Kafka接收器。Kafka将只看到新数据。

     b)不允许kafka接收器更改为文件接收器。

     c)Kafka接收器更改为foreach接收器是允许的,反之亦然。

4.输出接收器参数的更改:是否允许这样做以及更改的语义是否定义良好取决于接收器和查询。例如:

     a)不允许更改File Sink的接收路径

     b)Kafka Sink可以更改发布到的Topic

     c)允许更改用户自定义的foreach接收器(即ForeachWriter代码),但是更改的语义取决于代码。

5.映射/过滤器等的更改,有些情况下是允许的,例如:

     a)添加或删除过滤操作是允许的,例如sdf.selectExpr("a")更改为 sdf.where(...).selectExpr("a").filter(...).

     b)输出格式不变的情况下更改字段映射是允许的,例如sdf.selectExpr("stringColumn AS json").writeStream 更改为 sdf.selectExpr("anotherStringColumn AS json").writeStream

     c)更改输出格式只在部分情况下允许,例如sdf.selectExpr("a").writeStream 更改为sdf.selectExpr("b").writeStream 只在输出接收器允许将"a"变更为"b"的情况下才被允许。

说明:这里需要说明下Spark的Streaming中有有状态的(stateful)和无状态的(stateless)两种转化操作。其中有状态转化指的是依赖之前的批次数据或者中间结果来计算当前批次的数据,例如updateStateByKey()和window()等,而无状态转化指的是不依赖先前批次的数据。例如map()、filter()、reduceByKey()等都是无状态的。

6.有状态操作的更改:流查询中的一些操作需要维护状态数据(状态数据指之前批次的数据或中间结果),以便持续更新结果。Structured Streaming自动地将状态数据检查点存储到高容错的存储工具中(例如,HDFS、AWS S3、Azure Blob存储),并在重启后重新存储。但是,这需要假定状态数据的模式(schema)在重新启动时保持不变。这意味着在重新启动之间不允许对流查询的有状态操作进行任何更改(添加、删除或模式修改)。以下是有状态操作的列表,为了确保状态恢复,这些操作的模式不应该在重新启动之间更改:

     a)流聚合,例如对于sdf.groupBy("a").agg(...)不允许更改分组键或聚合的数量或类型

     b)流式重复数据删除,例如,sdf. dropduplicate("a")。不允许更改分组键或聚合的数量或类型。

     c)stream-stream连接,例如sdf1.join(sdf2,.....)不允许更改模式(schema)或连接的列。不允许更改连接类型(外部或内部)。联接条件中的其他更改定义不清。

     d)任意有状态操作:例如,sdf.groupByKey(…).mapgroupswithstate(…)或sdf.groupByKey(…).flatmapgroupswithstate(…)。不允许更改用户定义状态的模式和超时类型。允许在用户定义的状态映射函数中进行任何更改,但是更改的效果取决于用户定义的逻辑。如果确实需要支持状态模式更改,那么我们可以使用支持模式迁移的编码/解码模式显式地将复杂的状态数据结构编码/解码为字节,然后,可以在查询重新启动之间随意更改avro状态模式,因为二进制数据状态能始终成功地恢复。

连续处理[实验性的]

连续处理是Spark 2.3中引入的一种新的实验性的流执行模式,它支持非常低(~1 ms)的端到端延迟,并具有至少一次容错的保证。与此相比,默认的微批处理引擎可以实现精确的一次保证,但最多只能实现100毫秒的延迟。对于某些类型的查询(下面将讨论),可以选择在不修改应用程序逻辑(即不更改DataFrame/Dataset操作)的情况下以何种模式执行它们。

要在连续处理模式下运行受支持的查询,只需要指定一个具有所需检查点间隔的连续触发器作为参数。例如,

import org.apache.spark.sql.streaming.Trigger

spark
  .readStream
  .format("rate")
  .option("rowsPerSecond", "10")
  .option("")

spark
  .readStream
  .format("kafka")
  .option("kafka.bootstrap.servers", "host1:port1,host2:port2")
  .option("subscribe", "topic1")
  .load()
  .selectExpr("CAST(key AS STRING)", "CAST(value AS STRING)")
  .writeStream
  .format("kafka")
  .option("kafka.bootstrap.servers", "host1:port1,host2:port2")
  .option("topic", "topic1")
  .trigger(Trigger.Continuous("1 second"))  // 查询中唯一需要更改的地方
  .start()

检查点间隔为1秒意味着持续处理引擎将每秒记录查询的进度。生成的检查点的格式与微批处理引擎兼容,因此可以使用任何触发器重新启动任何查询。例如,以微批处理模式启动的受支持查询可以在连续模式下重启,反之亦然。需要注意的是,任何时候切换到连续处理模式,都能至少获得一次的容错保证。 

支持的查询

从Spark 2.3开始,连续处理模式只支持以下类型的查询。

①源(Sources):

    Kafka Source:所有操作的都支持

    Rate Source:主要用于测试。在连续模式下支持的选项只有numpartition和rowsPerSecond。

②操作(Operations):

    连续模式下只支持类似map的Dataset/DataFrame操作,即只支持投影(select、map、flatMap、mapPartitions等)和选择(where、filter等)。除了聚合函数(因为聚合还不受支持)、current_timestamp()和current_date()之外,所有SQL函数都能支持(使用时间进行确定性计算具有挑战性)。

③接收器(Sinks):

    Kafka Sink:所有操作都支持

    Memory Sink:主要用于测试

    Console Sink:主要用于测试,支持所有操作。控制台将打印在连续触发器中指定的每个检查点间隔。

警告说明

1.持续处理引擎启动多个长时间运行的任务,这些任务不断地从源读取数据、处理数据并持续地向接收器写入数据。查询所需的任务数量取决于查询可以从源并行读取多少个分区。因此,在开始连续处理查询之前,必须确保集群中有足够多的核来并行处理所有任务。例如,如果正在从一个包含10个分区的Kafka主题中读取数据,那么集群必须至少有10个内核才能使查询取得进展。

2.停止连续处理的流查询可能会产生错误的任务终止警告。这些可以安全的忽略。

3.目前没有失败任务的自动重试。任何错误都会导致查询被停止,并且需要从检查点手动重新启动查询。

 

 

Structured Streaming的部分算是看完啦,对于实时的数据统计分析来说它将会是最好的帮手!建议使用Spark 2.3以上的版本,很多新特性都是在这个版本增加的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值