跳转至

集群组件异常重试机制

集群组件异常重试机制

MPP数据库处理用户请求的过程

在一个MPP数据库中,参与数据查询的数据库组件包括Coordinator和Executor。在包含多个Coordinator和多个Executor的集群环境下,用户的数据库操作请求的执行过程大致如下:

  1. 在执行DDL语句时,接收用户请求的Coordinator节点负责权限和语法检查,之后把DDL语句分发给其他的Coordinator和Executor,待所有Coordinator和Executor都执行完该DDL后,返回给接收用户请求的Coordinator,该Coordinator返回最终结果给客户端。Coordinator与其他Coordinator、Coordinator与Executor执行通过指令传输通道进行通信。

  2. 在执行查询语句时,接收用户请求的Coordinator节点负责协调查询计划、元数据管理和查询优化,而Executor节点负责存储数据和执行查询操作。这些节点之间需要进行通信以协调其工作。如下是执行查询语句时Coordinator与Executor之间通信的一般流程:

    • 初始化阶段:在启动时,Coordinator节点会加载元数据信息,包括数据库的结构、表信息、分布式数据布局等。
    • 查询计划分发:当一个查询被提交到MPP时,Coordinator节点会根据查询优化器生成一个查询计划。然后,Coordinator会将查询计划分解成适合分段节点处理的片段,并将这些片段分发到相应的Executor节点。
    • 并行执行:每个Executor节点独立地执行其分配的查询片段。这可能涉及扫描本地存储的数据、执行计算等操作。Executor节点之间可能需要通过网络进行数据交换,以支持并行执行。
    • 数据交换:在执行查询过程中,如果某些操作需要从一个Executor节点获取另一个Executor节点上的数据,数据交换就会发生。这可能涉及到将数据通过网络传输从一个Executor节点发送到另一个Executor节点。
    • 结果汇总:在Executor节点完成其分配的操作后,结果会被发送回Coordinator节点,以便在Coordinator节点上进行汇总和组合。
    • 查询完成和结果返回:一旦Coordinator节点接收到所有Executor节点的结果,并对其进行汇总和组合,它将生成最终的查询结果并将其返回给客户端。

    执行查询的过程中,Coordinator节点与Executor节点之间的通信主要通过网络协议实现,包括指令通信(包括查询计划分发)和数据通信。

下面两个图,是Coordinator与Executor之间的指令通信和数据通信示意图:

集群组件间通讯示意图

通过语句重试机制消除组件异常对用户请求的影响

用户的请求需要多个Coordinator和Executor参与,如果组件间的网络互联发生异常,或者个别组件宕机,或者运维需要降级主节点提升备节点等,都会造成用户请求的执行失败。语句重试机制在用户直接连接的Coordinator内实现。当这个Coordinator在与其他组件交互时,发现其他组件异常,不立刻报错给用户,而是内部尝试重新执行用户的请求。通过重试,如果其他组件在重试的窗口期内恢复了正常,则视为用户请求执行成功,返回用户正常执行的结果。

语句重试机制是由用户直接连接的Coordinator发起的,当它检查到有其他组件发生了可以重试的错误时,会进行语句重试。这个检查组件错误的时间点主要有如下几个:

  • Coordinator与其他Coordinator或Executor建立连接来分发指令或分发执行计划时,如果与其他Coordinator或Executor建立连接失败,会重试建立连接的操作。
  • Coordinator发送两阶段事务提交命令给其他Coordinator或Executor时发生错误,会重新发送该两阶段命令。
  • Coordinator在等待其他Coordinator或Executor执行结束,而其他的Coordinator或Executor返回了执行异常的错误信息,导致当前语句执行失败。如果这个执行异常的错误信息是由于互联的网络错误引起的;或者是其他的Coordinator与Executor收到了shutdown信号引起的;或者其他的Coordinator或Executor上有其它进程宕机引起的。则会触发重试。

对于最后一种情况,如果当前执行出错的语句是没有开启事务的单条查询,则重试时只会重新执行本条语句。如果当前执行出错的语句在一个事务内,则重试时会先中止当前的事务,并从事务的开始语句开始执行,直到重试完之前出错的语句,把结果返回给用户,然后等待用户的进一步输入。执行重试时,发起重试的Coordinator会重新建立与其他Coordinator和Executor的连接。重试前创建的临时表在新建立的连接上是不存在的,所以如果重试语句访问之前的临时表,会报错该临时表不存在。

如果Coordinator在重试最后一种错误,ps -aux查看其seaboxsql的后端进程,会有RETRY字样进行提示。例如RETRY SELECT即在重试一个SELECT语句。

语句重试机制涉及的控制参数

如下的GUC参考控制重试机制的行为:

  • sc_execute_error_retry_count
  • 可重试错误发生后,最大的重试次数,每次重试之间会有10秒钟的时间间隔。
  • 默认值5, 有效值[0, 65536]

  • sc_gang_creation_retry_count

  • Coordinator与其他Coordinator和Executor建立连接时报错,重试的次数
  • 默认值20,有效值[0, 128]

  • dtx_phase2_retry_second

  • 两阶段事务提交阶段出错时重试的时间,单位为秒
  • 默认值600, 有效值[0, INT_MAX]

  • max_retry_cached_entries

  • 如果开启了事务,事务内每条语句都会缓存到重试语句的列表中,这个参数控制这个重试列表的长度
  • 默认值102400, 有效值[1, 1024000]

另外,对于进行节点替换等操作的场景,希望长时间进行重试,不再受上面的重试次数的限制,可以通过utility模式连上coordinator执行 select sc_force_retry_ic_error(true); 来设置强制重试而不计次数。这个函数执行后对所有现有的连接都会立刻生效。当节点替换操作执行完,通过utility模式连接Coordinator,执行 select sc_force_retry_ic_error(false);来退出强制重试的模式。