以DAG方式安排作业

我们有一个不同types的工作系统。 我们来举个例子:

job_1 job_2 job_3 

它们都需要不同的参数组(和可选参数)。 即我们运行job_1(x)为不同的x= A, B, C ... job_2运行一组取决于job_1(x)的结果的参数, job_1(x)也加载job_A(x)存储的数据。 等等。

结果是依赖关系的树形结构。 现在,这些工作偶尔会因为某种原因失败。 所以,如果job_A for x=B失败,树的分支将完全失败,不应该运行。 所有其他分支应该运行。

所有的作业都是用Python编写的,并使用并行(基于产生SLURM作业)。 他们计划与cron。 这显然不是很严重,有两个主要的缺点:

  • debugging非常困难。 所有的工作运行,无论是否在树上更高的工作失败。 如果没有深入理解依赖关系,很难看到问题出在哪里。
  • 如果较高的作业(例如job_A )未完成, job_B可能会计划运行,并失败或基于过期date运行。

为了解决这个问题,我们正在研究用于排程或可视化的气stream,因为它是用Python编写的,似乎大致符合我们的需求。 我看到了不同的挑战:

  • 作业的依赖关系树是非常普遍的(即job_B取决于job_A )或者非常广泛的(即job_B(y)对于100个参数取决于job_A(x=A) 。第一种情况下的可视化树会有大约10个叶子但会使debugging变得非常困难,因为这个工作对于某个参数来说可能是失败的,后一种情况下的可视化树会非常宽,大约有300个树叶,这样做会更准确,但是可视化可能很难阅读。我们过滤失败的工作,只看他们的依赖?
  • 我们在工作内部有平行性(我们需要它,否则工作超过一天,而且我们希望每天都重新运行整个工作)是否搞砸了我们的调度?
  • 我们希望尽可能less地改变我们的工作和数据pipe理。
  • 我们能否以一种容易理解的方式执行下一步产生什么工作的规则体系?

气stream是一个很好的select吗? 我知道还有一些其他的(luigi,Azkaban等),这些与Hadoop堆栈有些相关(我们没有使用,因为它不是大数据)。 需要多less黑客? 多less黑客是明智的?

我真的不能说气流,但我可以说luigi。

Luigi简介:Luigi专为数据流和数据依赖而设计,就像气流一样,但在Spotify开发。 数据流中的每一步都表示为从luigi.Task继承的类,并且我们将每个步骤称为任务。 每个任务由三个主要功能组成,并具有参数声明。 三个功能及其描述:

  1. 要求:在这个函数中,通过返回这些任务来指定当前任务所依赖的任务。
  2. 输出:在此函数中,通过返回类Luigi.LocalTarget(或类似的,但是远程的)的对象来指定将保存此任务的结果的位置。
  3. 运行:在此函数中,指定运行任务时实际发生的情况。

注意:luigi中央调度程序通过检查文件是否存在来知道任务何时完成,特别是在要运行的任务的require函数中返回的任务的输出函数中指定的文件。

我们可以过滤失败的工作,只看他们的依赖?

Luigi记录传递给每个任务的所有参数,每个参数都尝试运行每个任务。 默认情况下,luigi不保存日志,但是你可以很容易地设置它。 去年夏天,我制作了一个大的luigi管道,我保存了原木。 然后使用模糊的字符串比较(使用Levenshtein库)来删除重复的行,并严重压缩日志,然后基本上搜索单词“错误”,如果出现,那么它会发送一封电子邮件给我登录它。

我们在工作内部有平行性(我们需要它,否则工作超过一天,而且我们希望每天都重新运行整个工作)是否搞砸了我们的调度?

我在内部并行运行任务,没有任何问题。 有些图书馆可能会导致问题,例如gensim。

我们希望尽可能少地改变我们的工作和数据管理。

通常只需将大量计算粘贴到luigi任务的运行功能即可。

我们能否以一种容易理解的方式执行下一步产生什么工作的规则体系?

我相信是的。 对于每个任务,您可以指定在任务的require函数中依赖哪个任务。

还有一些需要考虑的是文档。 路易吉的文件是相当不错的,但它没有尽可能严重地陷入困境。 路易吉的社区不是很大,也不是非常活跃。 据我所知,气流是相当可比的,但是它更新,所以现在可能有一个更活跃的社区。

这里是一篇写luigi的人的博客文章,简单地比较luigi和新的替代方法。 他的结论是: 他们都很糟糕。 包括路易吉。