首页
解决方案
数据库专业技术服务全栈式PostgreSQL解决方案Oracle分布式存储化数据库云PolarDB一体化解决方案
产品
CLup:PostgreSQL高可用集群平台 CMiner: PostgreSQL中的CDC CData高性能数据库云一体机 CBackup数据库备份恢复云平台 CPDA高性能双子星数据库机 CSYun超融合虚拟机产品 ZQPool数据库连接池 ConshGuard数据保护产品 APCC: Greenplum管理平台
文档
文章
客户及伙伴
中启开源
关于我们
公司简介 联系我们
中启开源
登录
×
修改密码

RisingWave 技术文档(一)

概念篇:流数据库的本质

“数据就像河流,一旦流过就消失了。传统数据库试图用静态的容器去盛动态的水,而流数据库选择让计算随数据流动。”


1.1 从批处理到流处理:数据处理范式的演进

两种计算模型的诞生

在计算机科学的发展历程中,数据处理范式经历了两次重大变革。

批处理(Batch Processing) 是第一种被广泛采用的计算模型。在这种模式下,数据被收集起来,存储在某个地方,然后周期性地进行处理。传统的数据仓库就是批处理的典型代表——数据每天或每小时被 ETL 流程抽取、转换、加载,用户查询的是已经「凝固」的历史快照。

流处理(Stream Processing) 则代表了另一种思维:数据一旦产生就应该立即被处理,而不是等待积累到某个阈值。Kafka、Flink 等流处理框架的兴起,正是为了满足实时性的需求。

实时化的行业趋势

为什么流处理变得越来越重要?让我们看几个场景:

场景 批处理延迟 流处理延迟
电商实时大屏 5-15 分钟 < 1 秒
金融交易监控 分钟级 毫秒级
异常检测报警 小时级 秒级
推荐系统特征 小时级 实时

当业务对「时效性」的要求越来越高,批处理的局限性就愈发明显。

传统架构的无奈

然而,传统的流处理架构并不美好。一个典型的实时数据栈可能是这样的:

  1. 数据源 Kafka Flink 多个数据库 应用
  2. 又一个 Flink 另一个数据库
  3. 第三个 Flink ...

为什么会变成这样?

原因一:状态管理需要外部存储。 Flink 等流处理引擎的内部状态需要持久化,但引擎本身不擅长做数据存储,于是不得不把结果导出到专门的数据库。

原因二:跨流计算需要消息队列。 当一个流计算的输出需要作为另一个流的输入时,就需要 Kafka 这样的消息队列来传递数据。

原因三:查询能力需要独立数据库。 流处理引擎擅长计算,但不擅长随机查询,所以又需要独立的查询数据库。

结果就是:运维五六个组件,系统间的一致性需要手工保证,故障排查困难,扩缩容更是噩梦。

流数据库的诞生,就是为了解决这个「组件膨胀」的难题。


1.2 流数据库的核心概念

RisingWave 是一款面向流处理的分布式数据库。理解 RisingWave,首先要理解它的几个核心概念。

Table:数据的容器

在 RisingWave 中,Table 是一个有状态的数据表。与传统数据库类似,用户可以在 Table 上执行 Insert、Update、Delete 操作。

  1. -- 创建一个物理表
  2. CREATE TABLE orders (
  3. order_id BIGINT PRIMARY KEY,
  4. user_id BIGINT,
  5. amount DECIMAL,
  6. created_at TIMESTAMP
  7. );
  8. -- 如果指定了 CONNECTOR,数据会自动同步
  9. CREATE TABLE orders_with_connector (
  10. order_id BIGINT PRIMARY KEY,
  11. user_id BIGINT,
  12. amount DECIMAL,
  13. created_at TIMESTAMP
  14. ) WITH (
  15. connector = 'kafka',
  16. kafka.topic = 'orders',
  17. kafka.brokers = 'localhost:9092'
  18. );

当为 Table 连接上游 Source(如 Kafka)后,RisingWave 会自动追踪数据变化。当用户在 PostgreSQL 中执行一笔订单写入时,Debezium 会捕获这条变更日志(Change Log),RisingWave 内部会同步更新对应的 Table 内容。

Table 的特点:

Materialized View:持续计算的结果

如果说 Table 是数据的「容器」,那么 Materialized View(物化视图) 就是数据加工的「生产线」。

传统的 View 只是一个查询的「别名」——每次访问都会重新执行底层查询。而 Materialized View 会把查询结果持久化下来:

  1. -- 创建一个物化视图:实时统计每小时销售额
  2. CREATE MATERIALIZED VIEW hourly_sales AS
  3. SELECT
  4. date_trunc('hour', created_at) AS hour,
  5. SUM(amount) AS total_amount,
  6. COUNT(*) AS order_count
  7. FROM orders
  8. GROUP BY date_trunc('hour', created_at);

与传统数据库的静态物化视图不同,RisingWave 的 Materialized View 是动态持续更新的:

  1. 新订单写入 自动触发增量计算 物化视图结果实时更新

这意味着,当你在物化视图上执行 SELECT 时,返回的不是「上次查询时的快照」,而是「此时此刻的最新结果」。

物化视图的特点:

  1. 一致性:物化视图与基表的数据总是一致的(通过事务保证)
  2. 持久化:结果存储在 Hummock 中,支持高并发查询
  3. 可级联:可以在物化视图上再创建物化视图
  4. 增量更新:无需重算全量数据,只更新受影响的部分
  1. -- 级联物化视图示例
  2. CREATE MATERIALIZED VIEW user_hourly_stats AS
  3. SELECT
  4. u.user_id,
  5. u.username,
  6. h.hour,
  7. h.total_amount,
  8. h.order_count
  9. FROM users u
  10. JOIN hourly_sales h ON u.user_id = h.user_id; -- 基于上面的物化视图

这种级联能力是流处理的核心优势——将复杂的业务逻辑拆解为多个简单的步骤,每个步骤的结果都可以被复用和组合。

流表对偶性:数学美的视角

在理论层面,流处理有一个优雅的概念:流表对偶性(Stream-Table Duality)

是表的变更日志(Change Log)
是流的物化结果(Materialized Stream)

这个对偶性可以用一个简单的等式表达:

  1. = STREAM(变更日志)
  2. = TABLE(历史版本)

从 Table 到 Stream:
当 Table 发生 Insert、Update、Delete 时,每一条变更操作本身就是一个「事件」。这些事件组成的序列,就是 Stream。

从 Stream 到 Table:
当一个 Stream 被物化时,每一个时间点的状态就构成 Table 的一个快照。Table 是 Stream 在某个时刻的积分。

理解这个对偶性有什么用?

它帮助我们意识到:物化视图本质上是 Stream→Table 的转换,而 CDC(Change Data Capture)则是 Table→Stream 的转换。

RisingWave 正是基于这个原理,实现了流与表的无缝衔接。


1.3 流处理的高级语义

流处理之所以不同于传统的数据库查询,是因为它引入了几个独特的时间相关概念。

时间窗口(Windowing)

在流处理中,数据是「无限」的——没有终止边界。但业务往往需要对某个「时间段」的数据进行聚合,这就需要时间窗口。

滚动窗口(Tumbling Window)

固定大小、不重叠的窗口。例如每小时的销售额:

  1. SELECT
  2. window_start,
  3. window_end,
  4. SUM(amount) AS total_amount
  5. FROM TUMBLING(
  6. orders,
  7. INTERVAL '1' HOUR,
  8. created_at
  9. )
  10. GROUP BY window_start, window_end;

滑动窗口(Sliding Window)

窗口大小固定,但可以重叠。例如计算最近 5 分钟的移动平均:

  1. SELECT
  2. window_start,
  3. window_end,
  4. AVG(amount) AS moving_avg
  5. FROM SLIDING(
  6. orders,
  7. INTERVAL '5' MINUTE,
  8. INTERVAL '1' MINUTE, -- 滑动步长
  9. created_at
  10. )
  11. GROUP BY window_start, window_end;

会话窗口(Session Window)

基于活动的窗口,当不活动超过一定时间后窗口关闭:

  1. SELECT
  2. window_start,
  3. window_end,
  4. user_id,
  5. COUNT(*) AS action_count
  6. FROM SESSION(
  7. user_events,
  8. INTERVAL '5' MINUTE, -- 不活动间隔
  9. user_id
  10. )
  11. GROUP BY window_start, window_end, user_id;

水位线(Watermark)

在现实世界中,数据经常是乱序延迟到达的。想象一下:用户在 10:59 提交了一笔订单,但由于网络原因,这条数据在 11:05 才被处理。

水位线是流处理中处理乱序数据的一种机制:

  1. -- 定义水位线策略:允许最多 5 分钟的乱序
  2. CREATE SOURCE orders_source (
  3. ...
  4. )
  5. WITH (
  6. watermark = 'event_time - INTERVAL 5 MINUTE'
  7. );

RisingWave 会根据水位线判断:

这种机制让系统在「实时性」和「正确性」之间取得平衡。

EMIT 策略

默认情况下,物化视图的结果在窗口关闭(Window Close)时才会 Emit(输出)。但有些场景需要更早看到结果:

  1. -- 窗口未关闭时也输出中间结果
  2. SELECT
  3. window_start,
  4. window_end,
  5. SUM(amount) AS running_total
  6. FROM orders
  7. GROUP BY window_start, window_end
  8. EMIT ON WINDOW CLOSE; -- 默认:窗口关闭时输出
  9. -- 或者每分钟输出一次(Early Emit
  10. SELECT ...
  11. EMIT EVERY INTERVAL '1' MINUTE; -- 每分钟输出当前窗口状态

这个特性在需要「尽早看到部分结果」的场景下非常有用,比如实时监控仪表盘。


1.4 Source 与 Sink:数据的门户

Source:数据入口

Source 是数据进入 RisingWave 的入口。与 Table 不同,Source 本身不存储数据,它只是定义了「从哪里读取数据」。

  1. -- 创建一个 Kafka Source
  2. CREATE SOURCE kafka_orders (
  3. order_id BIGINT,
  4. user_id BIGINT,
  5. amount DECIMAL,
  6. created_at TIMESTAMP
  7. )
  8. WITH (
  9. connector = 'kafka',
  10. kafka.topic = 'orders',
  11. kafka.brokers = 'localhost:9092',
  12. kafka.scan.startup.mode = 'earliest'
  13. ) FORMAT PLAIN ENCODE JSON;

支持的数据源类型:

类型 说明
Kafka 主流消息队列
Pulsar 云原生消息平台
PostgreSQL 通过 CDC 同步
MySQL 通过 Debezium CDC
S3 批式导入

Source 的数据进入 RisingWave 后,会进入内部的流处理管道。用户可以选择:

  1. 直接物化到 TableCREATE TABLE ... FROM source_name
  2. 进入处理管道CREATE MATERIALIZED VIEW ... FROM source_name

Sink:数据出口

Sink 是计算结果的输出目的地:

  1. -- 创建一个 Kafka Sink,将实时统计结果发送到下游
  2. CREATE SINK hourly_sales_sink AS
  3. SELECT
  4. hour,
  5. total_amount,
  6. order_count
  7. FROM hourly_sales
  8. WITH (
  9. connector = 'kafka',
  10. kafka.topic = 'hourly_sales',
  11. kafka.brokers = 'localhost:9092'
  12. );

常见的 Sink 类型:

类型 用途
Kafka 传递给下游流处理系统
PostgreSQL 同步到分析型数据库
ClickHouse 进一步分析
S3 冷存储/归档

完整的数据流

一个典型的 RisingWave 数据流是这样的:

  1. [MySQL] --CDC--> [RisingWave Table]
  2. [Materialized View 1]
  3. [Materialized View 2] --Sink--> [Kafka]
  4. [Materialized View 3] --Sink--> [ClickHouse]

用户只需要定义「做什么」,RisingWave 负责「怎么做」和「什么时候做」。


1.5 小结

让我们用一张图来总结流数据库的核心概念:

  1. ┌─────────────────────────────────────────────────────────────────┐
  2. RisingWave 流数据库
  3. ├─────────────────────────────────────────────────────────────────┤
  4. ┌─────────┐ ┌─────────────┐
  5. Source ──────────────────────────▶│ Materialized
  6. (Kafka) View
  7. └─────────┘ └──────┬──────┘
  8. ┌─────────┐ ┌─────▼─────┐
  9. Table │◀─── CDC 同步 ────────────────│ Streaming
  10. │(MySQL) Pipeline
  11. └─────────┘ └─────┬─────┘
  12. ┌───────▼───────┐
  13. Sink
  14. (Kafka/PG/S3)
  15. └────────────────┘
  16. └─────────────────────────────────────────────────────────────────┘

核心要点回顾:

  1. Table vs Materialized View:Table 是数据的容器,MV 是计算的结果
  2. 流表对偶性:Stream 是 Table 的变更日志,Table 是 Stream 的物化结果
  3. 时间窗口:在无限的数据流上定义有限的分析区间
  4. 水位线:处理乱序和延迟数据的安全机制
  5. Source/Sink:数据的进出端口,内部通过流处理管道连接

下一篇预告

在理解了核心概念之后,我们将深入 RisingWave 的内部架构。你将了解到:

敬请期待:《架构篇:RisingWave 的系统设计》


想了解更多?