“分布式系统的设计,从来不是在单点最优和全局效率之间做选择题。RisingWave 选择用 SQL 作为统一的抽象,让用户专注于业务逻辑,而非底层复杂性。”
传统的大数据系统(如早期的 Apache Storm、Flink)采用存算耦合架构:计算节点本地存储状态,一旦节点宕机,恢复时需要把全部状态从远端拉回本地。这个过程可能需要数分钟甚至更长时间。
RisingWave 从第一天就选择了存算分离:
┌─────────────────────────────────────────────────────────────────┐│ 传统架构 │├─────────────────────────────────────────────────────────────────┤│ ││ Compute Node 1 ──────── 本地磁盘(状态) ││ ↓ ││ Compute Node 2 ──────── 本地磁盘(状态) ││ ↓ ││ Compute Node 3 ──────── 本地磁盘(状态) ││ ││ 问题:扩缩容需要迁移本地状态,速度慢 ││ │└─────────────────────────────────────────────────────────────────┘┌─────────────────────────────────────────────────────────────────┐│ RisingWave 架构 │├─────────────────────────────────────────────────────────────────┤│ ││ Compute Node 1 ──缓存──▶ S3 / MinIO (Hummock) ││ ↓ ▲ ││ Compute Node 2 ──缓存──▶ │ ││ ↓ │ 共享存储 ││ Compute Node 3 ──缓存──▶ S3 / MinIO (Hummock) ││ ││ 优点:节点扩缩容无需迁移状态,启动即用 ││ │└─────────────────────────────────────────────────────────────────┘
在 RisingWave 中,计算节点的本地状态只是缓存,真正的数据持久化在远端对象存储(S3、MinIO、HDFS)。当一个节点宕机重启时,它不需要拉回全部状态——它从空缓存开始,遇到 Cache Miss 时再从远端按需拉取数据。这就是秒级故障恢复的秘密。
Apache Flink 的出现让流处理变得更易用,但 Java/Python API 仍然有陡峭的学习曲线。
RisingWave 选择了纯 SQL 作为接口:
更重要的是,RisingWave 实现了一套完整的 SQL 优化器——它不只是把 SQL 翻译成执行计划,而是像传统数据库一样进行查询优化(谓词下推、列裁剪、Join 重排序等)。
在云原生时代,系统的弹性决定了对资源的利用率:
RisingWave 采用四节点分离架构,每种节点各司其职:
┌─────────────────────────────────────────────────────────────────┐│ 客户端 (PostgreSQL Driver) │└─────────────────────────────────────────────────────────────────┘│▼┌─────────────────────────────────────────────────────────────────┐│ Frontend Node ││ ┌─────────┐ ┌──────────┐ ┌────────────┐ ┌─────────────┐ ││ │ Binder │→ │ Optimizer │→ │ Planner │→ │Stream Frag- │ ││ │ │ │ (87+规则)│ │ │ │ menter │ ││ └─────────┘ └──────────┘ └────────────┘ └─────────────┘ │└─────────────────────────────────────────────────────────────────┘│ │ │▼ ▼ ▼┌────────────────┐ ┌────────────────┐ ┌────────────────┐│ Meta Node │ │ Compute Node │ │ Storage ││ ┌───────────┐ │ │ ┌───────────┐ │ │ ┌───────────┐ ││ │ Global │ │ │ │ Stream │ │ │ │ Hummock │ ││ │ Barrier │ │ │ │ Manager │ │ │ │ State │ ││ │ Manager │ │ │ └───────────┘ │ │ │ Store │ ││ └───────────┘ │ │ ┌───────────┐ │ │ └───────────┘ ││ ┌───────────┐ │ │ │ Actor │ │ │ ││ │ Catalog │ │ │ │ Manager │ │ │ ││ │ Manager │ │ │ └───────────┘ │ │ ││ └───────────┘ │ │ ┌───────────┐ │ │ ││ ┌───────────┐ │ │ │ Batch │ │ │ ││ │ Fragment │ │ │ │ Executor │ │ │ ││ │ Scheduler │ │ │ └───────────┘ │ │ ││ └───────────┘ │ │ │ │ │└────────────────┘ └────────────────┘ └────────────────┘
Frontend 负责接收 SQL 请求,产出可执行的计划。它包含几个关键组件:
Binder:将 SQL 语句绑定到实际的 catalog 对象(表、视图、函数等)。当用户写 SELECT * FROM orders 时,Binder 会解析 orders 指向哪个表,它的列是什么。
Optimizer:应用 87+ 优化规则,将逻辑计划转化为更高效的物理计划。RisingWave 使用 Volcano-style 优化模型,类似于 PostgreSQL 和 ORCA。
Planner:将优化后的计划转换为可执行的形式。对于流处理任务,Stream Fragmenter 负责将计划拆分为多个「Fragment」,每个 Fragment 可以在不同节点并行执行。
Meta 节点负责整个集群的协调工作,是名副其实的「大脑」:
GlobalBarrierManager:管理 Barrier 的生成和分发。Barrier 是 RisingWave 实现分布式快照和 Exactly-Once 语义的关键机制。
Catalog Manager:管理元数据(表、视图、函数、数据源等)。
Fragment Scheduler:将 Frontend 生成的执行计划调度到 Compute 节点。
Compute 节点是实际执行计算的地方。每个 Compute 节点运行两个主要的执行引擎:
Stream Executor:处理流式数据,持续不断地消费输入数据并更新物化视图。
Batch Executor:处理用户发起的即时查询。
Hummock 是 RisingWave 的存储引擎,构建在对象存储之上。它采用 LSM-tree 结构,提供高性能的读写能力,同时支持 MVCC 实现快照隔离。
流处理引擎是 RisingWave 的核心,负责持续消费数据并更新物化视图。
RisingWave 的流处理采用 Actor 模型:
每个 Actor 内部由多个 Executor 组成,每个 Executor 负责一种计算逻辑:
| Executor | 职责 |
|---|---|
| Filter | 行过滤 |
| Project | 列投影 |
| HashJoin | 流式 Hash Join |
| Aggregate | 聚合运算 |
| TopN | Top-N 排序 |
| WatermarkFilter | 水印过滤 |
| Source | 数据源读取 |
| Sink | 数据输出 |
| MView | 物化视图维护 |
Barrier 是 RisingWave 实现分布式快照和 Exactly-Once 语义的核心机制。
Barrier 本质上是一个带有Epoch 编号的特殊消息。它在流经整个 DAG 时,同时携带了「在这个 Epoch 之前的所有数据都已经到达」的信号。
Chandy-Lamport 算法
RisingWave 的 Barrier 同步基于经典的 Chandy-Lamport 分布式快照算法。这个算法能够在不停止流处理的情况下,获取分布式系统的全局一致状态。
Checkpoint 频率
RisingWave 默认的 Checkpoint 间隔是 10 秒——这远低于业界通常的 1-3 分钟。
Batch 查询的执行遵循「树形结构」:
SQL 前端负责将用户输入的 SQL 转化为可执行的分布式计划。
SQL Text → SQL Parser → Binder → Logical Plan → Optimizer → Physical Plan → Stream Fragmenter
Hummock 是 RisingWave 的核心存储引擎,它的命名来自《Donkeys》系列漫画中一只喜欢吃垃圾的小动物——寓意它善于处理「别人不要的垃圾」( compaction 的旧数据)。
Hummock 采用 LSM-tree(Log-Structured Merge-tree) 结构。
写入路径:
读取路径:
Hummock 使用 Epoch-based MVCC 实现快照隔离。
核心要点回顾:
下一篇预告
在理解了架构之后,我们将深入 RisingWave 的核心特性。你将了解到:
敬请期待:《特性篇:核心优势与一致性保障》
想了解更多?