如何避免在具有多个集群和并行工作的开发人员的数据块工作区中发生 jar 冲突?

How to avoid jar conflicts in a databricks workspace with multiple clusters and developers working in parallel?

我们在一个环境中工作,多个开发人员使用以下配置将 jar 上传到 Databricks 集群:

DBR: 7.3 LTS
Operating System: Ubuntu 18.04.5 LTS
Java: Zulu 8.48.0.53-CA-linux64 (build 1.8.0_265-b11)
Scala: 2.12.10
Python: 3.7.5
R: R version 3.6.3 (2020-02-29)
Delta Lake: 0.7.0
Build tool: Maven

以下是我们的典型工作流程:

第 0 步:

使用以下对象构建版本 1 的 jar (DemoSparkProject-1.0-SNAPSHOT.jar):

object EntryObjectOne {

  def main(args:Array[String]): Unit = {
    val spark = SparkSession.builder()
      .appName("BatchApp")
      .master("local[*]")
      .getOrCreate()

    import spark.implicits._

    println("EntryObjectOne: This object is from 1.0 SNAPSHOT JAR")

    val df: DataFrame = Seq(
      (1,"A","2021-01-01"),
      (2,"B","2021-02-01"),
      (3,"C","2021-02-01")
    ).toDF("id","value", "date")

    df.show(false)
  }
}

第 1 步:

从集群中卸载旧的jar(s),并在后续版本中不断推送新的变化,对逻辑进行小的改动。因此,我们推送 2.0-SNAPSHOT、3.0-SNAPSHOT 等版本的 jar

在某个时间点,当我们在 jar 中使用以下代码推送相同的对象时说 (DemoSparkProject-4.0-SNAPSHOT.jar):

object EntryObjectOne {

  def main(args:Array[String]): Unit = {
    val spark = SparkSession.builder()
      .appName("BatchApp")
      .master("local[*]")
      .getOrCreate()

    import spark.implicits._

    println("EntryObjectOne: This object is from 4.0 SNAPSHOT JAR")

    val df: DataFrame = Seq(
      (1,"A","2021-01-01"),
      (2,"B","2021-02-01"),
      (3,"C","2021-02-01")
    ).toDF("id","value", "date")

    df.show(false)
  }
}

当我们在 notebook 和 运行 主函数中导入这个对象时,我们仍然得到旧的快照版本 jar println 语句(EntryObjectOne: This object is from 1.0 SNAPSHOT JAR)。这迫使我们 运行 在 dbfs:/FileStore/jars/* 上删除并重新启动集群并再次推送最新快照以使其正常工作。

本质上当我运行 sc.listJars() 驱动程序中的活动jar 是最新的4.0-SNAPSHOT jar。然而,我仍然看到旧快照 jar 的逻辑,即使它们没有在 运行 时间安装在集群上。

我们tried/implemented的决议:

这是在 DataBricks 中处理多个 jar 版本的正确方法吗?如果在DataBricks中有更好的方法来处理这个版本冲突问题,那将对我们有很大帮助。

您不能使用打包为 Jar 的库 - 当您安装库时,它会被放入类路径中,并且只有在您重新启动集群时才会被删除。文档 says explicitly about that

When you uninstall a library from a cluster, the library is removed only when you restart the cluster. Until you restart the cluster, the status of the uninstalled library appears as Uninstall pending restart.

这与“普通”Java 程序的问题相同,Java 只是不支持此功能。例如,参见 this question.

的答案

对于 Python & R 来说更容易,因为它们支持笔记本范围的库,不同的笔记本可以有相同库的不同版本。

P.S。如果您正在进行 unit/integration 测试,我的建议是将测试作为 Databricks 作业执行 - 它会更便宜,并且您不会在不同版本之间发生冲突。

除了文档中提到的内容:使用笔记本时,您可以通过 运行 在笔记本单元格中了解驱动程序中添加的内容:

%sh
ls /local_disk0/tmp/ | grep addedFile

这对我在 Azure Databricks 上有用,它会列出所有添加的 jar。 也许用初始化脚本强制清理?