Executor
1.架构图
系统的特点如下:
在群集中的每个节点上启动 Executor 进程,为用户提供 JDBC 服务。用户可以连接到任何节点。
Executor 相互提供 TaskExec 服务,以进行任务分配、管理和执行。
DDL 和 DCL 操作直接调用 Dingo SDK 中的相应接口。
DML 和 DQL 操作被转化为任务,任务中的操作符调用 Dingo SDK 中的读写操作。
2.在 Dingo 中的作用
充当 SQL 服务器,解析和响应来自客户端的 SQL 请求和其他管理请求,并执行 JDBC 协议。
管理任务并实现任务的分布式执行。
通过 SDK 调用底层 Meta 和 Store API,实现数据库功能。
3.SQL 执行程序
APP 通过驱动程序客户端启动与 JDBC 服务器的连接。
APP 向 JDBC 服务器发送 SQL 执行请求。
JDBC 服务器会对接收到的 SQL 命令进行解析、验证和优化,逐步生成逻辑执行计划、物理执行计划和任务。
JDBC 服务器会将作业中的任务分配给 TaskExec 服务,并返回 ResultSet。
APP 发起数据检索请求。
JDBC 服务器向 TaskExec 服务发送运行命令。
任务开始运行,生成的数据被推送到下游的 JDBC 服务器。
JDBC 服务器会将数据返回给 APP。
如果数据没有完全返回,APP 会启动另一个数据检索请求,然后重复步骤 5、7 和 8,直到所有数据都返回为止(运行命令无需再次发送)。 用户连接数据库、执行 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)。 |