+++
pre = "<b>3.2. </b>"
title = "弹性调度"
weight = 2
chapter = true
+++

弹性调度是 ElasticJob 最重要的功能，也是这款产品名称的由来。
它是一款能够让任务通过分片进行水平扩展的任务处理系统。

## 分片

ElasticJob 中任务分片项的概念，使得任务可以在分布式的环境下运行，每台任务服务器只运行分配给该服务器的分片。
随着服务器的增加或宕机，ElasticJob 会近乎实时的感知服务器数量的变更，从而重新为分布式的任务服务器分配更加合理的任务分片项，使得任务可以随着资源的增加而提升效率。

任务的分布式执行，需要将一个任务拆分为多个独立的任务项，然后由分布式的服务器分别执行某一个或几个分片项。

举例说明，如果作业分为 4 片，用两台服务器执行，则每个服务器分到 2 片，分别负责作业的 50% 的负载，如下图所示。

![分片作业](https://shardingsphere.apache.org/elasticjob/current/img/elastic/sharding.png)

### 分片项

ElasticJob 并不直接提供数据处理的功能，而是将分片项分配至各个运行中的作业服务器，开发者需要自行处理分片项与业务的对应关系。
分片项为数字，始于 0 而终于分片总数减 1。

### 个性化分片参数

个性化参数可以和分片项匹配对应关系，用于将分片项的数字转换为更加可读的业务代码。

例如：按照地区水平拆分数据库，数据库 A 是北京的数据；数据库 B 是上海的数据；数据库 C 是广州的数据。
如果仅按照分片项配置，开发者需要了解 0 表示北京；1 表示上海；2 表示广州。
合理使用个性化参数可以让代码更可读，如果配置为 0=北京,1=上海,2=广州，那么代码中直接使用北京，上海，广州的枚举值即可完成分片项和业务逻辑的对应关系。

## 资源最大限度利用

ElasticJob 提供最灵活的方式，最大限度的提高执行作业的吞吐量。
当新增加作业服务器时，ElasticJob 会通过注册中心的临时节点的变化感知到新服务器的存在，并在下次任务调度的时候重新分片，新的服务器会承载一部分作业分片，如下图所示。

![作业扩容](https://shardingsphere.apache.org/elasticjob/current/img/elastic/sacle-out.png)

将分片项设置为大于服务器的数量，最好是大于服务器倍数的数量，作业将会合理的利用分布式资源，动态的分配分片项。

例如：3 台服务器，分成 10 片，则分片项分配结果为服务器 A = 0,1,2,9；服务器 B = 3,4,5；服务器 C = 6,7,8。
如果服务器 C 崩溃，则分片项分配结果为服务器 A = 0,1,2,3,4; 服务器 B = 5,6,7,8,9。
在不丢失分片项的情况下，最大限度的利用现有资源提高吞吐量。

## 高可用

当作业服务器在运行中宕机时，注册中心同样会通过临时节点感知，并将在下次运行时将分片转移至仍存活的服务器，以达到作业高可用的效果。
本次由于服务器宕机而未执行完的作业，则可以通过失效转移的方式继续执行。如下图所示。

![作业高可用](https://shardingsphere.apache.org/elasticjob/current/img/elastic/ha.png)

将分片总数设置为 1，并使用多于 1 台的服务器执行作业，作业将会以 1 主 n 从的方式执行。
一旦执行作业的服务器宕机，等待执行的服务器将会在下次作业启动时替补执行。开启失效转移功能效果更好，如果本次作业在执行过程中宕机，备机会立即替补执行。

## ElasticJob-Lite 实现原理

ElasticJob-Lite 并无作业调度中心节点，而是基于部署作业框架的程序在到达相应时间点时各自触发调度。
注册中心仅用于作业注册和监控信息存储。而主作业节点仅用于处理分片和清理等功能。

### 弹性分布式实现

- 第一台服务器上线触发主服务器选举。主服务器一旦下线，则重新触发选举，选举过程中阻塞，只有主服务器选举完成，才会执行其他任务。
- 某作业服务器上线时会自动将服务器信息注册到注册中心，下线时会自动更新服务器状态。
- 主节点选举，服务器上下线，分片总数变更均更新重新分片标记。
- 定时任务触发时，如需重新分片，则通过主服务器分片，分片过程中阻塞，分片结束后才可执行任务。如分片过程中主服务器下线，则先选举主服务器，再分片。
- 通过上一项说明可知，为了维持作业运行时的稳定性，运行过程中只会标记分片状态，不会重新分片。分片仅可能发生在下次任务触发前。
- 每次分片都会按服务器IP排序，保证分片结果不会产生较大波动。
- 实现失效转移功能，在某台服务器执行完毕后主动抓取未分配的分片，并且在某台服务器下线后主动寻找可用的服务器执行任务。

### 注册中心数据结构

注册中心在定义的命名空间下，创建作业名称节点，用于区分不同作业，所以作业一旦创建则不能修改作业名称，如果修改名称将视为新的作业。
作业名称节点下又包含5个数据子节点，分别是 config, instances, sharding, servers 和 leader。

### config 节点

作业配置信息，以 YAML 格式存储。

### instances 节点

作业运行实例信息，子节点是当前作业运行实例的主键。
作业运行实例主键由作业运行服务器的 IP 地址和 PID 构成。
作业运行实例主键均为临时节点，当作业实例上线时注册，下线时自动清理。注册中心监控这些节点的变化来协调分布式作业的分片以及高可用。
可在作业运行实例节点写入 TRIGGER 表示该实例立即执行一次。

### sharding 节点

作业分片信息，子节点是分片项序号，从零开始，至分片总数减一。
分片项序号的子节点存储详细信息。每个分片项下的子节点用于控制和记录分片运行状态。
节点详细信息说明：

| 子节点名  | 临时节点 | 描述                                                                      |
| -------- |:------- |:------------------------------------------------------------------------- |
| instance | 否      | 执行该分片项的作业运行实例主键                                                |
| running  | 是      | 分片项正在运行的状态<br />仅配置 monitorExecution 时有效                      |
| failover | 是      | 如果该分片项被失效转移分配给其他作业服务器，则此节点值记录执行此分片的作业服务器 IP |
| misfire  | 否      | 是否开启错过任务重新执行                                                     |
| disabled | 否      | 是否禁用此分片项                                                            |

### servers 节点

作业服务器信息，子节点是作业服务器的 IP 地址。
可在 IP 地址节点写入 DISABLED 表示该服务器禁用。
在新的云原生架构下，servers 节点大幅弱化，仅包含控制服务器是否可以禁用这一功能。
为了更加纯粹的实现作业核心，servers 功能未来可能删除，控制服务器是否禁用的能力应该下放至自动化部署系统。

### leader 节点

作业服务器主节点信息，分为 election，sharding 和 failover 三个子节点。
分别用于主节点选举，分片和失效转移处理。

leader节点是内部使用的节点，如果对作业框架原理不感兴趣，可不关注此节点。

| 子节点名              | 临时节点 | 描述                                                                        |
| -------------------- |:------- |:--------------------------------------------------------------------------- |
| election\instance    | 是      | 主节点服务器IP地址<br />一旦该节点被删除将会触发重新选举<br />重新选举的过程中一切主节点相关的操作都将阻塞   |
| election\latch       | 否      | 主节点选举的分布式锁<br />为 curator 的分布式锁使用 |
| sharding\necessary   | 否      | 是否需要重新分片的标记<br />如果分片总数变化，或作业服务器节点上下线或启用/禁用，以及主节点选举，会触发设置重分片标记<br />作业在下次执行时使用主节点重新分片，且中间不会被打断<br />作业执行时不会触发分片 |
| sharding\processing  | 是      | 主节点在分片时持有的节点<br />如果有此节点，所有的作业执行都将阻塞，直至分片结束<br />主节点分片结束或主节点崩溃会删除此临时节点 |
| failover\items\分片项 | 否      | 一旦有作业崩溃，则会向此节点记录<br />当有空闲作业服务器时，会从此节点抓取需失效转移的作业项 |
| failover\items\latch | 否      | 分配失效转移分片项时占用的分布式锁<br />为 curator 的分布式锁使用                    |

### 流程图

#### 作业启动

![作业启动](https://shardingsphere.apache.org/elasticjob/current/img/principles/job_start.jpg)

#### 作业执行

![作业执行](https://shardingsphere.apache.org/elasticjob/current/img/principles/job_exec.jpg)
