Spark 流作业的可靠检查点(保持复杂状态)

rak*_*esh 5 apache-spark spark-streaming

我们在 Red Hat 4.4.7 上使用 Spark 1.6 和 JVM 1.6 来运行我们的 Spark 流应用程序/作业。我们的一些流作业使用复杂的状态,我们有 Scala 案例类来表示它们。但是在测试作业的升级周期时,我们遇到了一些问题,如下所示。由于流作业将永远运行,因此在设计易于升级的应用程序方面需要帮助。

我正在检查作业无法从检查点重新启动的确切用例。

  • 只是重新启动作业而不更改任何内容并不会产生问题。
  • 在进行随机更改(与状态无关)后重新启动作业不会产生问题。
  • 在更改状态处理功能(例如通过添加打印)后重新启动作业不会产生问题。
  • 在更改状态(通过添加新的布尔字段)后重新启动作业确实会产生问题。

在做了一些谷歌搜索之后,处理这个问题的一般准则似乎是,

  1. 将状态实现为“将模式与数据一起存储的格式”,如 json 或 avro。
    • 客户端代码必须在将其放入状态之前进行序列化,并在从状态中读取后反序列化。序列化和反序列化将在每个流间隔后发生,mapWithState 可能会有所帮助。
    • 如果作业的多个版本可以共存,则必须明确处理将状态从版本 x 升级到 y !!!
  2. 停止输入,完成输入的处理,重新开始作为具有新检查点的新作业。
    • 虽然这很容易实现,但对于我们的一些工作来说是不可能的。升级周期也会变得稍微复杂一些。
  3. 同时将数据保存到外部存储,并在升级时将其加载为初始 RDD。
    • 这将引入保持状态的外部依赖。
    • 如果作业的多个版本可以共存,则必须明确处理将状态从版本 x 升级到 y !!!

由于信息分散在整个网络上,我感到很困惑,无法得出结论。以下是我的问题,

  1. 如果状态类的结构发生变化,检查点将变得无效,但是,如果状态类的程序集 jar 或功能(不是结构)发生变化,是否还有其他已知问题使检查点变得无效?
  2. 您使用什么策略来轻松升级有状态的 Spark 流作业?

rak*_*esh 1

考虑像 jvm/scala/spark/etc 这样的环境升级的情况......无论发生任何变化,都不能保证检查点可以永远可靠。

检查点旨在仅帮助在不幸的故障/崩溃事件中进行恢复,而不是用作数据存储!

最好的替代方案是定期将数据刷新到可靠的存储(HDFS/DB/等)中,并在发生任何形式的升级时读取与初始 RDD 相同的数据。