3. 生产集群部署与配置基线

Trino 的生产集群不是“装好就能跑”的组件,而是一套需要按查询负载、并发规模、数据源分布和故障容忍度来规划的分布式 SQL 引擎。部署基线的核心目标只有两个:让 Coordinator 稳定地做解析、优化和调度,让 Worker 稳定地做扫描、聚合和交换。围绕这个目标,本节从集群规划、节点角色、JVM 与内存、资源组、会话属性、高可用与滚动升级六个方面给出可落地的配置基线。

一、集群规划与节点角色

Trino 集群由 Coordinator 和 Worker 两类角色组成。Coordinator 负责接收 SQL、生成执行计划、拆分 Stage 与 Task、调度到 Worker,并汇总最终结果;Worker 负责执行 Task、读取 Connector 数据、参与 Shuffle 与聚合。生产环境不建议 Coordinator 同时承担 Worker 计算,否则大查询的调度延迟会明显上升。

规划时先估算并发查询数与单查询内存。假设一个中等规模集群需要支撑 30 个并发查询,每个查询平均占用 20 GB 内存,则 Worker 侧至少需要 600 GB 可用查询内存。若单台 Worker 配置 256 GB 物理内存,其中约 70% 可用于查询,即 180 GB,则至少需要 4 台 Worker 才能满足内存需求;再考虑故障冗余和峰值,建议部署 6 台 Worker。Coordinator 单独一台,配置可略低于 Worker,但 JVM 堆不宜过小,建议 32~64 GB。

节点角色规划建议如下:Coordinator 节点承担 discovery、调度和结果汇总,不配置为 Worker;Worker 节点按机架或可用区均匀分布,避免同一机架故障导致整个集群不可用;元数据存储(如 Hive Metastore、Iceberg Catalog)与 Trino 分开部署,避免元数据压力影响查询执行。

Trino 生产集群角色与资源规划示意 Coordinator SQL 解析 / 优化 / 调度 JVM Heap 32–64 GB 不承担 Worker 计算 Discovery Service 节点注册与心跳 与 Coordinator 同进程 端口 8080 Worker 池 6 台 × 256 GB 内存 查询内存约 180 GB/台 按机架均匀分布 资源组 Resource Group global.etl:maxRunning=10 global.bi:maxRunning=20 hardConcurrencyLimit 隔离 会话属性基线 query_max_run_time=2h query_max_memory=100GB join_distribution_type=AUTOMATIC 高可用与滚动升级 Coordinator 主备切换 Worker 分批重启 升级前 drain 查询 JVM 与内存配置基线 -Xmx 与 -Xms 设为相同值,避免堆动态伸缩;G1GC 为主,大堆可评估 ZGC;query.max-memory-per-node 不超过堆的 70% memory.heap-headroom-per-node 预留 30%;Worker 堆建议 64–128 GB,Coordinator 堆 32–64 GB

二、JVM 与内存配置

Trino 是 JVM 应用,内存配置直接决定查询能否稳定完成。生产环境建议将 -Xmx 与 -Xms 设为相同值,避免堆在运行期反复伸缩带来的停顿。Worker 堆大小建议 64~128 GB,Coordinator 堆建议 32~64 GB。堆过大时 G1GC 的回收停顿可能变长,超过 128 GB 可评估 ZGC。

关键参数包括:query.max-memory-per-node 控制单节点查询内存上限,建议不超过堆的 70%;memory.heap-headroom-per-node 为堆预留空间,默认 30%,生产环境不建议调低;query.max-total-memory-per-node 控制单节点总内存,通常与前者配合使用。以下是一份 Worker 的 jvm.config 示例:

-server
-Xmx96G
-Xms96G
-XX:+UseG1GC
-XX:G1HeapRegionSize=32M
-XX:+ExplicitGCInvokesConcurrent
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/trino/heapdump
-XX:+ExitOnOutOfMemoryError
-Djdk.attach.allowAttachSelf=true

对应的 config.properties 内存相关配置:

query.max-memory=600GB
query.max-memory-per-node=64GB
query.max-total-memory-per-node=80GB
memory.heap-headroom-per-node=30%

这里 query.max-memory 是集群级上限,应小于所有 Worker 可用查询内存之和,避免单个大查询拖垮整个集群。

三、资源组与会话属性

资源组用于按业务线隔离并发和内存。生产环境通常按 ETL、BI、Ad-hoc 划分。以下是一个资源组配置示例,使用文件方式加载:

{
  "rootGroups": [
    {
      "name": "global",
      "softMemoryLimit": "80%",
      "hardConcurrencyLimit": 50,
      "maxQueued": 100,
      "subGroups": [
        {
          "name": "etl",
          "softMemoryLimit": "50%",
          "hardConcurrencyLimit": 10,
          "maxQueued": 30
        },
        {
          "name": "bi",
          "softMemoryLimit": "30%",
          "hardConcurrencyLimit": 20,
          "maxQueued": 50
        },
        {
          "name": "adhoc",
          "softMemoryLimit": "20%",
          "hardConcurrencyLimit": 5,
          "maxQueued": 10
        }
      ]
    }
  ]
}

会话属性用于给不同业务设置默认行为。例如 BI 查询通常需要限制运行时长和内存,避免单个看板查询占用过多资源:

query_max_run_time=2h
query_max_memory=100GB
query_max_total_memory=150GB
join_distribution_type=AUTOMATIC
redistribute_writes=true

这些属性可以通过 resource-groups.properties 中的 resource-groups.config-file 指向资源组 JSON,再结合 session-property-manager 按用户或来源设置默认值。

四、高可用与滚动升级策略

Coordinator 是单点,生产环境建议部署主备两个 Coordinator,通过负载均衡或 VIP 对外提供服务。主 Coordinator 故障时,备节点接管,客户端重连即可。Worker 无状态,故障后由 Coordinator 重新调度 Task,但正在运行的查询会失败,需要重试。

滚动升级时,先升级 Worker 再升级 Coordinator。Worker 分批重启,每批不超过总数的 20%,重启前通过 SHUTTING_DOWN 状态让节点停止接收新 Task,等待现有 Task 完成后再停止进程。升级 Coordinator 前,先确认没有正在运行的关键查询,再切换主备。以下是一个滚动升级检查清单:

阶段操作判断依据
升级前确认无长查询、无失败 TaskSELECT * FROM system.runtime.queries WHERE state='RUNNING' 返回为空
Worker 批次每批重启 20% Worker批次内节点全部 UP,查询成功率恢复
Coordinator 切换主备切换后观察 5 分钟新查询正常提交,无大量 QUEUED
升级后验证版本与关键查询SELECT version() 返回目标版本
生产基线建议:Coordinator 与 Worker 分离部署;Worker 堆 96 GB、查询内存 64 GB;资源组按 ETL/BI/Ad-hoc 隔离;会话属性限制单查询时长与内存;滚动升级按 20% 批次执行,升级前确认无运行中查询。

以上配置不是一次设定就永久有效。随着并发增长、数据量变化和查询模式演进,需要定期回顾 query.max-memory、资源组并发上限和 Worker 数量,结合 system.runtime.queries 与 system.memory 的观察结果做调整。部署基线的价值在于让集群在可预期的边界内运行,而不是追求单次查询的极限性能。