核心概念与架构:Server/Broker/Controller 角色、Segment 与 Table、Tenant 与 Tag

好,咱们正式开始聊 Pinot 的骨架。

很多人第一次接触 Pinot,会被一堆角色搞晕:Server、Broker、Controller…… 这仨到底谁干活?Segment 和 Table 又是什么关系?Tenant 和 Tag 是不是同一个东西?

别急,我一个个拆开讲。你把这些概念理清了,后面调优、排错会顺手很多。

三大核心角色:谁负责什么

Pinot 的架构是典型的「无共享」分布式设计。三个角色各司其职,配合得像流水线一样。

一句话总结:Controller 管元数据,Broker 管查询路由,Server 管数据存储和计算。

1. Controller

Controller 是集群的「大脑」。它负责管理 Table 的元数据、Segment 的分配、以及集群的健康状态。

  • 元数据管理:Table 的 schema、配置、Segment 的分布信息,全在 Controller 里。
  • 负载均衡:当 Server 挂掉或新增时,Controller 自动重新分配 Segment。
  • 任务调度:比如离线数据的 Segment 推送、实时数据的 Segment 提交,都由 Controller 触发。

我的经验:Controller 本身不存数据,但它挂了整个集群就「失明」了。生产环境至少部署 3 个 Controller 做 ZK 选主,别单点。

2. Broker

Broker 是「查询入口」。客户端发来的 SQL,先到 Broker 手里。

  • 解析与路由:Broker 解析 SQL,根据查询条件找到哪些 Server 上有对应的 Segment。
  • 结果合并:每个 Server 返回部分结果,Broker 做最终的聚合、排序、Limit 操作。
  • 缓存:Broker 可以缓存元数据,减少对 Controller 的请求。

注意:Broker 是无状态的。你可以随意扩缩容。我曾经遇到 Broker 内存不够,结果合并时 OOM,后来给 Broker 单独配了堆内存,问题解决。

3. Server

Server 是「苦力」。数据存在它这里,查询计算也在它这里跑。

  • 数据存储:每个 Server 持有若干 Segment 的副本。
  • 查询执行:收到 Broker 的请求后,Server 在本地扫描 Segment,做过滤、聚合,返回中间结果。
  • 实时与离线:Server 可以同时处理实时写入的 Segment 和离线导入的 Segment。

说白了,Server 是 Pinot 里最吃资源的角色。CPU、内存、磁盘,全看它。

Segment 与 Table:数据的基本单元

这两个概念容易混淆。我刚开始用 Pinot 时也绕了一阵子。

Table

Table 是逻辑概念。它定义了你查询的数据结构(schema)、数据源类型(离线/实时)、以及一些配置(如索引、分区)。

Pinot 里 Table 分两种:

类型 数据来源 典型场景
OFFLINE 批量导入(如 Hadoop、Spark) 历史数据、T+1 报表
REALTIME 流式写入(如 Kafka) 实时监控、秒级指标
HYBRID 两者结合 冷热数据分离查询

我建议:如果业务既有历史数据又有实时数据,用 HYBRID Table。离线部分存大时间范围,实时部分存最近几小时,查询时 Broker 自动合并结果。

Segment

Segment 是物理存储单元。一个 Table 的数据被切分成多个 Segment,每个 Segment 是一个独立的列存文件。

  • 不可变性:离线 Segment 一旦生成就不会再变。实时 Segment 在内存中积累,达到阈值后「提交」变成不可变文件。
  • 副本与分布:每个 Segment 可以有多个副本,分布在不同的 Server 上,保证高可用。
  • 索引:每个 Segment 内部可以建倒排索引、Star-Tree 索引、范围索引等。

举个例子:你有一个 1TB 的订单表,Pinot 会把它切成几百个 200MB 左右的 Segment。查询时,Broker 只路由到包含相关数据的 Segment,而不是全表扫描。

核心关系:Table 是「逻辑视图」,Segment 是「物理分片」。一个 Table 包含多个 Segment,一个 Segment 只属于一个 Table。

Tenant 与 Tag:资源隔离的艺术

这是 Pinot 里比较「绕」的概念,但用好了非常强大。

Tag

Tag 是打在 Server 上的标签。比如你可以给一批 Server 打上 orders_OFFLINE,另一批打上 orders_REALTIME。

Tag 的命名规则是:表名_类型。类型可以是 OFFLINE、REALTIME、BROKER。

Tenant

Tenant 是 Tag 的集合。它把 Server 和 Broker 分组,实现物理资源隔离。

举个例子:

  • 你有一个「订单分析」业务,给它建一个 Tenant orders。
  • 这个 Tenant 包含一组 Server(打上 orders_OFFLINE 和 orders_REALTIME)和一组 Broker(打上 orders_BROKER)。
  • 订单 Table 的数据只会落到这些 Server 上,不会跟其他业务抢资源。
概念 作用 类比
Tag 给节点打标签 快递上的「易碎品」贴纸
Tenant 把标签分组,形成隔离域 公司的不同部门

避坑指南:我曾经在一个集群里,把多个业务的 Table 都放在默认 Tenant 下。结果一个业务的实时写入把 CPU 打满,其他业务的查询全挂了。后来强制每个业务建独立 Tenant,世界清净了。

架构总览:一张图说清

下面这张 SVG 图,把上面讲的三个角色、Segment/Table、Tenant/Tag 串在一起。你盯着看 30 秒,整个 Pinot 的骨架就印在脑子里了。

Pinot 核心架构图 Pinot 核心架构:角色、数据与资源隔离 Controller 元数据管理 / 负载均衡 Broker 查询路由 / 结果合并 Server (离线) Tag: orders_OFFLINE Server (实时) Tag: orders_REALTIME Segment 副本 Segment 副本 Table: orders Tenant: orders → 包含 Server(离线+实时) + Broker,实现资源隔离

你看,Controller 管全局,Broker 接查询,Server 存数据。Segment 是数据的最小单元,Table 是逻辑容器。Tenant 和 Tag 把不同业务的资源隔离开,互不干扰。

记住这个逻辑链:Table → 包含多个 Segment → Segment 分布在 Server 上 → Server 通过 Tag 归属到 Tenant → Tenant 隔离资源。

嗯,核心概念就这些。你把这些搞懂了,后面聊索引、查询优化、实时摄入,都会轻松很多。