核心概念与架构: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 的骨架就印在脑子里了。
你看,Controller 管全局,Broker 接查询,Server 存数据。Segment 是数据的最小单元,Table 是逻辑容器。Tenant 和 Tag 把不同业务的资源隔离开,互不干扰。
记住这个逻辑链:Table → 包含多个 Segment → Segment 分布在 Server 上 → Server 通过 Tag 归属到 Tenant → Tenant 隔离资源。
嗯,核心概念就这些。你把这些搞懂了,后面聊索引、查询优化、实时摄入,都会轻松很多。