分布式技术之分布式共享状态调度架构

发布时间:2023年12月28日

什么是共享状态调度?

  • 集群中需要管理的对象主要包括两种:
    • 一是,资源的分配和使用状态;
    • 二是,任务的调度和执行状态;
  • 在单体调度中,这两种对象都是由单体调度器管理的,因此可以比较容易地保证全局状态的一致性,但问题是可扩展性较差(支持业务类型受限),且存在单点瓶颈问题。而在两层调度中,这两种对象分别由第一层中央调度器和第二层 Framework 调度器管理,由于 Framwork 调度器只能看到部分资源,因此不能保证全局状态的一致性,也不容易实现全局最优的调度。
  • 为了解决这些问题,一种新的调度器架构被设计了出来。这种架构基本上沿袭了单体调度器的模式,通过将单体调度器分解为多个调度器,每个调度器都有全局的资源状态信息,从而实现最优的任务调度,提供了更好的可扩展性。也就是说,这种调度架构在支持多种任务类型的同时,还能拥有全局的资源状态信息。要做到这一点,这种调度架构的多个调度器需要共享集群状态,包括资源状态和任务状态等。因此,这种调度架构,我们称之为共享状态调度器

共享状态调度架构的示意图:
在这里插入图片描述

  • 共享状态调度架构为了提供高可用性和可扩展性,将集群状态之外的功能抽出来作为独立的服务。具体来说就是:

    • State Storage 模块(资源维护模块)负责存储和维护资源及任务状态,以便 Scheduler 查询资源状态和调度任务;
    • Resource Pool 即为多个节点集群,接收并执行 Scheduler 调度的任务;
    • Scheduler 只包含任务调度操作,而不是像单体调度器那样还需要管理集群资源等。
  • 共享状态调度也支持多种任务类型,但与两层调度架构相比,主要有两个不同之处:

    • 存在多个调度器,每个调度器都可以拥有集群全局的资源状态信息,可以根据该信息进行任务调度;
    • 共享状态调度是乐观并发调度,在执行了任务匹配算法后,调度器将其调度结果提交给 State Storage,由其决定是否进行本次调度,从而解决竞争同一种资源而引起的冲突问题,实现全局最优调度。而两层调度是悲观并发调度,在执行任务之前避免冲突,无法实现全局最优匹配。
  • 乐观并发调度和悲观并发调度的区别:

    • 乐观并发调度,强调事后检测,在事务提交时检查是否避免了冲突:若避免,则提交;否则回滚并自动重新执行。也就是说,它是在执行任务匹配调度算法后,待计算出结果后再进行冲突检测。
    • 悲观并发调度,强调事前预防,在事务执行时检查是否会存在冲突。不存在,则继续执行;否则等待或回滚。也就是说,在执行任务匹配调度算法前,通过给不同的 Framework 发送不同的资源,以避免冲突。

共享状态调度设计

  • 共享状态调度的理念最早是 Google 针对两层调度器的不足,提出的一种调度架构。这种调度结构的典型代表有 Google 的 Omega、微软的 Apollo,以及 Hashicorp 的 Nomad 容器调度器。
    在这里插入图片描述

Omega 调度架构

  • Omega 集群中有一个“Cell”的概念,每个 Cell 管理着部分物理集群,一个集群有多个 Cell。实际上,你可以直接将这里的“Cell”理解为一个集群的子集群或子节点的集合。

Omega 集群的调度架构示意图
在这里插入图片描述

  • State Storage 模块负责存储和维护资源及任务状态,里面有一个 Cell State 文件,记录着全局共享的集群状态。实际上,State Storage 组件中的集群资源状态信息,就是主本,而 Cell State 就是以主副本的形式存在的。每个调度器都包含一个私有的 Cell State 副本,也就是拥有了一个集群资源状态信息的副本,进而达到了共享集群资源状态信息的目的。
  • 在 Omega 系统中,没有中央资源分配器,所有资源分配决策都在调度器(Scheduler)中进行。每个调度器都可以根据私有的 Cell State 副本,来制定调度决策。调度器可以查看 Cell 的整个状态,并申请任何可用的集群资源。一旦调度器做出资源调度决策,它就会在原子提交中更新本地的 Cell State 的资源状态副本。若同时有多个调度器申请同一份资源,State Storage 模块可以根据任务的优先级,选择优先级最高的那个任务进行调度。
  • 在 Omega 系统中的每个调度器,都具有对整个集群资源的访问权限,从而允许多个调度器自由地竞争空闲资源,并在更新集群状态时使用乐观并发控制来调解资源冲突问题。这样一来,Omega 就有效地解决了两层调度中 Framework 只拥有局部资源,无法实现全局最优的问题。

Omega 共享调度工作原理

  • Omega 使用事务管理状态的设计思想,将集群中资源的使用和任务的调度类似于基于数据库中的一条条事务(Transaction)一样进行管理。显然,数据库是一个共享的状态,对应 Omega 中的 Cell State,而每个调度器都要根据数据库的信息(即集群的资源信息)去独立完成自己的任务调度策略。

  • 如下图所示,在一个应用执行的过程中,调度器会将一个 Job 中的所有 Task 与 Resource 进行匹配,可以说 Task 与 Resource 之间是进行多对多匹配的。其间,调度器会设置多个 Checkpoint 来检测 Resource 是否都已经被占用,只有这个 Job 的所有 Task 可以匹配到可用资源时,这个 Job 才可以被调度。
  • 这里的 Job 相当于一个事务,也就是说,当所有 Task 匹配成功后,这个事务就会被成功 Commit,如果存在 Task 匹配不到可用资源,那么这个事务需要执行回滚操作,Job 调度失败。
    在这里插入图片描述
  • 无论事务是否执行成功,调度器都会在事务执行之后,重新从主本那里同步更新本地 Cell State 的资源状态副本,以保证本地集群信息状态的有效性。若事务未成功执行,则调度器会在必要时重新运行其调度算法并再次尝试申请资源。调度器对 Job 的调度是具有原子性的,一个 Job 的所有 Task 都是一起调度的,即使部分 Task 调度失败了,调度器再次调度时也必须再次调度整个 Job。多个调度器可以并行调度,无需等待其他调度器调度结果,若存在冲突时,进行冲突处理,比如根据 Job 的优先级,优先级高则获得资源。
  • Omega 涉及了 Job 并发调度。针对这一点,Omega 采用了传统数据库中的乐观锁(MVCC,Multi-Version Concurrency Control,基于多版本的并发访问控制),即每一个应用都发放了所有的可用资源,在更新集群状态时使用乐观并发控制来解决资源冲突问题,来提高 Omega 的并发度。
  • Omega 调度器将两层调度器中的集中式资源调度模块简化成了一些持久化的共享数据(状态)和针对这些数据的验证代码。而这里的“共享数据”,实际上就是整个集群的实时资源状态信息,而验证代码就是解决调度冲突的调度规则。

单体调度、两层调度和共享调度的区别是什么?

三种调度的架构示意图
在这里插入图片描述

  • 单体调度,是由一个中央调度器去管理整个集群的资源信息和任务调度,也就是说所有任务只能通过中央调度器进行调度。
    • 这种调度架构的优点是,中央调度器拥有整个集群的节点资源信息,可以实现全局最优调度。但它的缺点是,无调度并发性,且中央服务器存在单点瓶颈问题,导致支持的调度规模和服务类型受限,同时会限制集群的调度效率。因此,单体调度适用于小规模集群。
  • 两层调度,是将资源管理和任务调度分为两层来调度。其中,第一层调度器负责集群资源管理,并将可用资源发送给第二层调度;第二层调度接收到第一层调度发送的资源,进行任务调度。
    • 这种调度架构的优点是,避免了单体调度的单点瓶颈问题,可以支持更大的服务规模和更多的服务类型。但其缺点是,第二层调度器往往只对全局资源信息有部分可观察性,因此任务匹配算法无法实现全局最优。双层调度适用于中等规模集群。
  • 共享状态调度,多个调度器,每个调度器都可以看到集群的全局资源信息,并根据这些信息进行任务调度。相较于其他两个调度架构来说,共享状态调度架构适用的集群规模最大。
    • 这种调度架构的优点是,每个调度器都可以获取集群中的全局资源信息,因此任务匹配算法可以实现全局最优性。但,也因为每个调度器都可以在全局范围内进行任务匹配,所以多个调度器同时调度时,很可能会匹配到同一个节点,从而造成资源竞争和冲突。
    • 虽然 Omega 的论文宣称可以通过乐观锁机制,避免冲突。但在工程实践中,如果没有妥善处理资源竞争的问题,则很可能会产生资源冲突,从而导致任务调度失败。这时,用户就需要对调度失败的任务进行处理,比如重新调度、任务调度状态维护等,从而进一步增加了任务调度操作的复杂度。

你知道的越多,你不知道的越多。

文章来源:https://blog.csdn.net/qq_40722827/article/details/135132498
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。