Executor

1.架构图

Executor 架构 系统的特点如下:

  • 在群集中的每个节点上启动 Executor 进程,为用户提供 JDBC 服务。用户可以连接到任何节点。

  • Executor 相互提供 TaskExec 服务,以进行任务分配、管理和执行。

  • DDL 和 DCL 操作直接调用 Dingo SDK 中的相应接口。

  • DML 和 DQL 操作被转化为任务,任务中的操作符调用 Dingo SDK 中的读写操作。

2.在 Dingo 中的作用

  • 充当 SQL 服务器,解析和响应来自客户端的 SQL 请求和其他管理请求,并执行 JDBC 协议。

  • 管理任务并实现任务的分布式执行。

  • 通过 SDK 调用底层 Meta 和 Store API,实现数据库功能。

3.SQL 执行程序

  1. APP 通过驱动程序客户端启动与 JDBC 服务器的连接。

  2. APP 向 JDBC 服务器发送 SQL 执行请求。

  3. JDBC 服务器会对接收到的 SQL 命令进行解析、验证和优化,逐步生成逻辑执行计划、物理执行计划和任务。

  4. JDBC 服务器会将作业中的任务分配给 TaskExec 服务,并返回 ResultSet。

  5. APP 发起数据检索请求。

  6. JDBC 服务器向 TaskExec 服务发送运行命令。

  7. 任务开始运行,生成的数据被推送到下游的 JDBC 服务器。

  8. JDBC 服务器会将数据返回给 APP。

  9. 如果数据没有完全返回,APP 会启动另一个数据检索请求,然后重复步骤 5、7 和 8,直到所有数据都返回为止(运行命令无需再次发送)。 用户连接数据库、执行 SQL 语句、然后退出的完整时序图如下所示:SQL 执行顺序

语句和作业并不是一对一的关系。一个 Statement 可以多次用于执行多个 SQL 语句,每个语句对应一个单独的作业。在任何时候,Statement 都只与一个作业相关联。

用户有两种方式启动 SQL 执行:

  • 直接执行是指使用 JDBC 接口的 Statement#execute(String sql) 方法来执行 SQL 语句。

直接执行

  • 准备和执行是指执行参数化 SQL 语句。该方法对应于 JDBC 接口的 Connection#prepareStatement(String sql) 方法。

准备执行

使用 JDBC 接口 Statement#execute() 方法执行 SQL 语句的处理流程如下:

准备执行

TaskExec 服务会缓存已分发的任务,因此可以通过 ID 找到已分发的任务,而无需重新分发。

“运行任务”命令将绑定参数传递给每个任务。

4.数据结构

一个任务由一个物理计划生成。一个任务包含多个任务,每个任务都有一个位置属性,用于指示执行任务的节点地址。

每个任务由多个操作符组成,每个操作符有一个或多个输入端口,称为Pins,从 0 开始编号。 操作符还有一个输出属性,代表所有输出端口,是一个输出列表。输出口可包含 0 到多个输出口,每个输出口都标明与之相连的下一级操作器的 ID 和Pins编号,从而形成一个有向无环图。

5.运行任务

任务通过 “推送数据 ”方法运行。一般来说,操作符的 push 方法表示向其某个端口输入数据。在处理完数据后,操作符可以直接调用 Output 的推送方法输出数据,而 Output 则直接调用下一级操作符的推送方法。

有些操作符不需要输入数据,称为源操作符。在这种情况下,它们的 push 方法是启动任务的入口点。任务启动时,需要并行调用每个源操作符的 push 方法。

有些操作符不输出数据,称为 SinkOperators。

操作符的 push 方法返回一个布尔值。如果为 false,则表示下一级操作符不需要更多数据。此时,需要停止数据处理并返回 false。当 SourceOperator 的 push 方法返回 false 时,它所在的线程将调用一次 fin 方法,然后退出。fin 方法的执行逻辑与 push 方法相同,但没有返回值。当任务的所有线程都退出时,任务执行结束。

下面是执行顺序图:

执行序列

线程首先调用 Scan 的 push 方法。在 push 方法中,Scan 会循环处理所有数据,并将其推送到下一级。当数据用完时,它会返回 false,然后任务线程调用 fin 方法并结束。如果 Root 的 push 方法返回 false(例如,当 SQL 语句中有 LIMIT 子句时),则 false 返回值会传播到上一级,并导致 Scan 提前终止枚举循环。

6.网络传输

通过一对发送和接收操作符,数据可以在节点之间传输。发送属于数据 SinkOperator,接收属于数据 SourceOperator。以下是在节点间传输数据的序列图:

数据传输顺序

为了提高传输效率,发送和接收都有相应的数据队列。发送队列推送一次数据后,不会立即发送,而是将其放入发送队列。当满足特定条件时,数据会被打包并作为一个整体发送。

数据通过发送和接收之间建立的逻辑通道传输,接收线程将接收到的数据拆包并放入接收队列。接收线程从接收队列中检索数据,并将其推送给下游操作员。

接收线程对发送方有以下三个回复:

Response

Meaning

发送接收到响应后的操作

READY

表示发送方可以继续发送数据

继续运行并向上游操作员返回 true

STOP

表示发送数据暂停

线程暂停,直到收到 READY 或 QUIT

QUIT

表示不需要更多数据

清除发送队列并向上游操作员返回 false(最后也会发送 FIN)。