版本控制策略

从 Spark 1.0.0 开始,Spark 项目将遵循语义化版本控制指南,但会有一些细微的偏差。这些差异考虑到 Spark 作为多模块项目的特性。

Spark 版本

每个 Spark 发行版都将采用如下版本号格式:[MAJOR].[FEATURE].[MAINTENANCE]

  • MAJOR(主版本号):所有主版本号相同的发行版都将保持 API 兼容性。主版本号将在很长一段时间内保持稳定。例如,1.X.Y 可能持续一年或更长时间。
  • FEATURE(功能版本号):功能版本通常包含新特性、改进和错误修复。每个功能版本都有一个合并窗口(可以合并新补丁)、一个 QA 窗口(仅允许合并修复程序),最后是一个针对候选发布版本进行投票的最终阶段。这些窗口将在上一个功能版本发布后立即公布,以便留给人们充足的时间。随着时间的推移,我们可能会使整个发布过程更加规律(类似于 Ubuntu)。
  • MAINTENANCE(维护版本号):维护版本发布频率较高,具体取决于所引入的补丁(例如错误修复)及其紧迫性。通常,这些版本旨在修补错误。但是,更高级别的库可以引入少量功能(例如新算法),前提是它们完全是累加的,且与现有代码路径隔离。Spark 核心部分可能不会引入任何新功能。

Alpha 组件

当新组件被添加到 Spark 中时,它们最初可能被标记为“alpha”。Alpha 组件不必遵守上述准则,但应尽可能地遵守。一旦它们被标记为“stable(稳定)”,就必须遵循这些准则。

API 兼容性

通常,API 是指 Spark 中记录的任何公共类或接口,例如 ScalaDoc。我们力求保证版本之间的源码兼容性和二进制兼容性。

请注意,即使对于“开发人员 API”和“实验性”功能,我们也努力保持最大程度的兼容性。如果计划在以后更改 API,则不应将代码作为“实验性”合并到项目中,因为用户期望从所有可用 API 中获得最大的兼容性。

破坏 API 时的考虑因素

Spark 项目力求避免破坏 API 或静默更改行为,即使是在主版本中也是如此。虽然这并不总是可能的,但在选择破坏 API 之前,应权衡以下因素。

破坏 API 的代价

破坏 API 对 Spark 用户来说几乎总是会产生不小的代价。损坏的 API 意味着 Spark 程序需要在升级前进行重写。然而,在考虑代价时需要注意以下几点:

  • 使用率 - 在许多不同地方被积极使用的 API,一旦破坏,代价总是非常昂贵的。虽然很难确切知道使用情况,但我们有多种方法可以进行估算:
    • 该 API 在 Spark 中存在了多久?

    • 即使对于基本程序,该 API 是否也是通用的?

    • 我们在 JIRA 或邮件列表中看到相关问题的频率如何?

    • 它在 StackOverflow 或博客中出现的频率如何?

  • 破坏后的行为 - 一个当前正常的程序在破坏后会怎样?以下按严重程度大致递增排序:

    • 会出现编译器或链接器错误吗?

    • 会出现运行时异常吗?

    • 该异常会在完成大量处理后发生吗?

    • 我们会静默地返回不同的结果吗?(非常难以调试,甚至可能根本无法察觉!)

维护 API 的代价

当然,以上并不意味着我们永远不会破坏任何 API。我们还必须考虑保持该 API 对项目本身及我们用户所产生的代价。

  • 项目成本 - 我们拥有的每一个 API 都需要进行测试,并需要在项目其他部分发生变化时保持正常工作。当外部依赖项(JVM、Scala 等)发生变化时,这些成本会显著加剧。在某些情况下,虽然并非技术上完全不可行,但维护特定 API 的代价可能变得过高。

  • 用户成本 - API 对学习 Spark 或试图理解 Spark 程序的用户也有认知成本。当所涉及的 API 具有令人困惑或未定义的语义时,这种成本会变得更高。

破坏 API 的替代方案

在存在“糟糕的 API”但移除代价很高的情况下,应考虑一些不会伤害现有用户但能解决部分维护成本的替代方案。

  • 避免糟糕的 API - 虽然这有点显而易见,但这是一个重要的点。当我们向 Spark 添加新接口时,我们应该考虑到我们可能永远无法摆脱这个 API。请深入思考新 API 与现有 API 的关系,以及您期望它们随着时间的推移如何演变。

  • 弃用警告 - 所有弃用警告都应指向一个明确的替代方案,而不应仅仅说明 API 已被弃用。

  • 更新文档 - 文档应指出执行特定任务的“最佳”推荐方法。在我们需要维护遗留文档的情况下,应明确指向较新的 API 并向用户建议“正确”的方法。

  • 社区工作 - 许多人通过阅读博客和 StackOverflow 等其他网站来学习 Spark。然而,这些资源中的许多已经过时。请更新它们,以降低最终移除已弃用 API 的成本。

发布节奏

分支每年的 1 月和 7 月切出,因此功能(“次要”)版本通常每 6 个月发布一次。因此,Spark 2.3.0 通常会在 2.2.0 发布约 6 个月后发布。维护版本在功能版本之间根据需要发布。主版本不遵循固定的发布时间表。

Spark 4.2 发布窗口

日期 活动
2026 年 5 月 1 日 代码冻结。切出发布分支。
2026 年 5 月中旬 QA 阶段。专注于错误修复、测试、稳定性和文档。通常不合并任何新功能。
2026 年 5 月下旬 候选发布版本 (RC)、投票等,直到最终版本通过。

维护版本和 EOL(生命周期结束)

功能发布分支通常会进行为期 18 个月的错误修复版本维护。例如,2.3.x 分支自 2019 年 9 月起不再被视为受维护状态,距离 2018 年 2 月发布的 2.3.0 过了 18 个月。此后不应再期望有 2.3.x 版本发布,即使是错误修复版本也是如此。

主版本中的最后一个次要版本通常会作为“LTS(长期支持)”版本维护更长时间。例如,3.5.0 于 2023 年 9 月 13 日发布,通常会维护 31 个月,直到 2026 年 4 月 12 日。

作为常规版本控制策略的例外,版本 3.5.x 拥有一个“扩展”LTS 期,以允许完成迁移。此扩展 LTS 期将于 2027 年 11 月结束。在 3.5.x 扩展 LTS 期内,我们仅包含安全修复程序。此扩展 LTS 仅适用于 Apache Spark 主项目/仓库,不适用于具有单独仓库/发布的子项目(即:Spark Connect for Swift/Rust/Go 和 Spark Kubernetes operator)。此外,由于 Java 8 的支持可能会从其他项目(包括 Hadoop)中移除,如果某个依赖项的安全修复程序未被移植到与 Java 8 兼容的版本,我们可能会决定将该漏洞标记为“不修复”或在不支持 Java 8 的情况下发布新版本。