用 4 行代码开启你的流计算之旅

作者: 吴英骏 RisingWave 创始人 & CEO

十年前,我接触了一个大数据项目,叫做 Stratosphere

这个项目仅用一个页面就吸引了我:使用 3 行代码就可以在单机上启动一个集群并使用MapReduce 方式计算 WordCount 程序。要知道,在 Hadoop 盛行的年代,从安装 Hadoop 到写 WordCount 程序跑起来都要花好几个小时。

当看到一个项目能够用 3 行代码就能做到同样功能的时候,很显然会令人眼前一亮。也是因为这 3 行代码,让我深度探索了这个项目,并在之后成为了这个项目的贡献者。

如今,那个曾经叫做 Stratosphere 的项目已经改名成 Apache Flink(Apache Flink® --- Stateful Computations over Data Streams),并且成为了大数据时代最火的流计算引擎。与之前那个 Stratosphere 不同的是,Flink 已经成为了一个庞大的项目,其复杂程度令人生畏。

而那个参与 Flink 最早一版流计算引擎设计开发的我,依然向往着极简的用户体验,期望用户能够开速上手,极速体验到简单高效的流计算。带着这一信念,我与小伙伴们一起打造了云时代的流数据库 RisingWave,为用户提供如使用 PostgreSQL 一般的高性能流计算体验。

在本文,我就为大家演示,如何使用 4 行代码,使用 RisingWave 开启你的流计算之旅。

什么是流计算

注:如果你对流计算已经有一定的认识,那么可以直接跳过这一段。

批计算与流计算是数据处理的两种最基本模式。在过去的 20 年中,批计算系统与流计算系统都经历了快速迭代,从单机时代到分布式时代,再从大数据时代到云时代,批计算系统与流计算系统均在架构上有了大幅改进。

(上图为:批计算与流计算在本世纪发展历程。)

批计算与流计算最核心的两个区别在于:

  • 批计算系统的计算由用户驱动,而流计算系统的计算由事件驱动;
  • 批计算系统采用全量计算模型,而流计算系统采用增量计算模型。

不管是批计算还是流计算,它们都是往"实时"这一方向发展。如今,批系统被广泛的运用在交互式分析场景中,而流计算系统则被广泛的运用在监控、告警、自动化等场景。

(上图为:实时批计算系统与实时流计算系统的对比。)

RisingWave:用 PostgreSQL 的体验进行流计算

RisingWave 是一款以 Apache 2.0 协议开源的 SQL 流数据库。它使用 PostgreSQL 兼容的接口,允许用户能像操作 PostgreSQL 数据库一样进行分布式流计算。

RisingWave 最典型的场景有两个:一个是流式 ETL,另一个是流式分析。

所谓流式 ETL,就是将各类消息源(如 OLTP 数据库、消息队列、文件系统等)经过加工之后(比如进行 join、aggregation、groupby、windowing 等)实时导入到终端系统(如 OLAP 数据库、数据仓库、数据湖等分析类系统,或是导回 OLTP 数据库、消息队列、文件系统中)。在该场景中,RisingWave 可完全替换 Apache Flink。

(上图为:流式 ETL场景)

所谓流式分析,就是将各类消息源(如 OLTP 数据库、消息队列、文件系统等)经过加工之后(比如进行 join、aggregation、groupby、windowing 等)直接呈现在终端 BI 报表中,或是允许用户直接使用不同语言客户端库访问。在该场景中,RisingWave 可替换 Apache Flink 与SQL/NoSQL 数据库(如 MySQL、PostgreSQL、Cassandra、Redis 等)的组合。

(上图为:流式分析场景)

4 行代码部署 RisingWave

首先在 Mac 的命令行窗口里执行三行命令安装并运行 RisingWave:

注:Linux 下安装请参考:Run RisingWave directly on your host machine | RisingWave

bash 复制代码
brew tap risingwavelabs/risingwave
brew install risingwave
risingwave playground

然后打开一个命令行窗口,执行以下命令连接到 RisingWave:

css 复制代码
psql -h localhost -p 4566 -d dev -U root

为了易于理解,我们先尝试创建一个表,并用INSERT来添加一些测试数据。在实际场景中,我们需要从消息队列里拿数据,那个部分留到后面再介绍。

我们来创建一个网页浏览记录的表:

sql 复制代码
CREATE TABLE website_visits (
  timestamp TIMESTAMP,
  user_id VARCHAR,
  page_id VARCHAR,
  action VARCHAR
);

接下来我们创建一个物化视图来统计每个页面的访问量,访问者数量,以及最后访问时间。这里要插一句,基于流数据的物化视图是 RisingWave 的一个核心功能。

sql 复制代码
CREATE MATERIALIZED VIEW page_visits_mv AS
SELECT page_id,
       COUNT(*) AS total_visits,
       COUNT(DISTINCT user_id) AS unique_visitors,
       MAX(timestamp) AS last_visit_time
FROM website_visits
GROUP BY page_id;

我们用 INSERT 来加入一些数据。

sql 复制代码
INSERT INTO website_visits (timestamp, user_id, page_id, action) VALUES
  ('2023-06-13T10:00:00Z', 'user1', 'page1', 'view'),
  ('2023-06-13T10:01:00Z', 'user2', 'page2', 'view'),
  ('2023-06-13T10:02:00Z', 'user3', 'page3', 'view'),
  ('2023-06-13T10:03:00Z', 'user4', 'page1', 'view'),
  ('2023-06-13T10:04:00Z', 'user5', 'page2', 'view');

看一下目前的结果:

sql 复制代码
SELECT * from page_visits_mv;

-----Results
 page_id | total_visits | unique_visitors |   last_visit_time

---------+--------------+-----------------+---------------------

 page2   |            2 |               2 | 2023-06-13 10:04:00

 page3   |            1 |               1 | 2023-06-13 10:02:00

 page1   |            2 |               2 | 2023-06-13 10:03:00

(3 rows)

让我们再插入 5 组数据:

sql 复制代码
INSERT INTO website_visits (timestamp, user_id, page_id, action) VALUES
  ('2023-06-13T10:05:00Z', 'user1', 'page1', 'click'),
  ('2023-06-13T10:06:00Z', 'user2', 'page2', 'scroll'),
  ('2023-06-13T10:07:00Z', 'user3', 'page1', 'view'),
  ('2023-06-13T10:08:00Z', 'user4', 'page2', 'view'),
  ('2023-06-13T10:09:00Z', 'user5', 'page3', 'view');

分两次插入数据是想模拟数据不停进入的过程。让我们再来看一下现在的结果:

sql 复制代码
SELECT * FROM page_visits_mv;
-----Results
 page_id | total_visits | unique_visitors |   last_visit_time

---------+--------------+-----------------+---------------------

 page1   |            4 |               3 | 2023-06-13 10:07:00

 page2   |            4 |               3 | 2023-06-13 10:08:00

 page3   |            2 |               2 | 2023-06-13 10:09:00

(3 rows)

我们看到结果已经更新。如果我们处理的是真正的流数据,那么这个结果是会自动保持最新的。

实现与 Kafka 交互

鉴于流数据处理中消息队列较为常用,我们可以来看一下如何实时获取并处理 Kafka 中的数据。

如果你还没安装 Kafka,那么先到官网下载合适的压缩包(这里以 3.4.0 为例),然后解压:

shell 复制代码
$ tar -xzf kafka_2.13-3.4.0.tgz
$ cd kafka_2.13-3.4.0

下面我们来启动 Kafka。

  1. 生成一个集群 UUID:

    <math xmlns="http://www.w3.org/1998/Math/MathML"> K A F K A C L U S T E R I D = " KAFKA_CLUSTER_ID=" </math>KAFKACLUSTERID="(bin/kafka-storage.sh random-uuid)"

  2. 格式化日志目录:

    <math xmlns="http://www.w3.org/1998/Math/MathML"> b i n / k a f k a − s t o r a g e . s h f o r m a t − t bin/kafka-storage.sh format -t </math>bin/kafka−storage.shformat−tKAFKA_CLUSTER_ID -c config/kraft/server.properties

  3. 启动 Kafka 服务器:

    $ bin/kafka-server-start.sh config/kraft/server.properties

启动 Kafka 服务器之后,我们可以创建一个话题(topic)。

css 复制代码
$ bin/kafka-topics.sh --create --topic test --bootstrap-server localhost:9092

创建成功后,我们就可以从命令行直接输入消息。

先运行以下命令启动生产者程序:

shell 复制代码
$ bin/kafka-console-producer.sh --topic test --bootstrap-server localhost:9092

待出现>符号时,我们可以输入消息了。为了方便在 RisingWave 消费数据,我们按照 JSON格式输入数据。

json 复制代码
{"timestamp": "2023-06-13T10:05:00Z", "user_id": "user1", "page_id": "page1", "action": "click"}
{"timestamp": "2023-06-13T10:06:00Z", "user_id": "user2", "page_id": "page2", "action": "scroll"}
{"timestamp": "2023-06-13T10:07:00Z", "user_id": "user3", "page_id": "page1", "action": "view"}
{"timestamp": "2023-06-13T10:08:00Z", "user_id": "user4", "page_id": "page2", "action": "view"}
{"timestamp": "2023-06-13T10:09:00Z", "user_id": "user5", "page_id": "page3", "action": "view"}

我们可以启动一个消费者程序来查看我们输入的消息。

css 复制代码
$ bin/kafka-console-consumer.sh --topic test --from-beginning --bootstrap-server localhost:9092

下面我们看一下在 RisingWave 怎么来获取这个消息队列的数据。在这个场景中,RisingWave扮演的是消息的消费者角色。我们现在回到 RisingWave 窗口(即 psql 窗口),创建一个数据源(source),这样就能与刚才创建的主题(topic)建立连接。需要注意的是,这里只是建立连接,还没真正的开始消费数据。

在创建数据源时,对于 JSON 类型的数据,我们可以直接定义 schema 来映射流数据中的相关字段。为了避免与上面的表重名,我们将数据源命名为website_visits_stream

ini 复制代码
CREATE source IF NOT EXISTS website_visits_stream (
	timestamp TIMESTAMP,
	user_id VARCHAR,
	page_id VARCHAR,
	action VARCHAR
	)
WITH (
	connector='kafka',
	topic='test',
	properties.bootstrap.server='localhost:9092',
	scan.startup.mode='earliest'
	)
ROW FORMAT JSON;

我们需要创建一个物化视图(materialized view)来让 RisingWave 开始摄取数据并进行计算。为了便于理解,我们创建了与上面的例子中类似的物化视图。

sql 复制代码
CREATE MATERIALIZED VIEW visits_stream_mv AS
	SELECT page_id,
	COUNT(*) AS total_visits,
	COUNT(DISTINCT user_id) AS unique_visitors,
	MAX(timestamp) AS last_visit_time
	FROM test
	GROUP BY page_id;

我们现在可以看一下结果:

sql 复制代码
SELECT * FROM visits_stream_mv;
-----Results

 page_id | total_visits | unique_visitors |   last_visit_time

---------+--------------+-----------------+---------------------

 page1   |            1 |               1 | 2023-06-13 10:07:00

 page2   |            3 |               2 | 2023-06-13 10:08:00

 page3   |            1 |               1 | 2023-06-13 10:09:00

(3 rows)

至此我们已经从 Kafka 里获取数据并对数据进行了处理。

进阶:用 RisingWave 搭一个实时监控系统

在流处理的应用中,实时监控是一个较为常见的需求。你可以在对数据进行实时处理后进行实时的可视化展示。RisingWave 可以作为数据源,直接接入可视化工具(例如 Superset, Grafana 等)并将处理后的指标数据进行实时展示。鼓励各位可以尝试一下自己搭建一个流处理+可视化展示的系统。具体的步骤可以参考我们的使用场景文档

在该文档中,我们使用RisingWave 来监控和处理系统运行指标,并实时在 Grafana 中展示。我们的演示较为简单,相信各位基于真实数据,在自己熟悉的业务场景中,能够实现丰富得多的展示效果。

(上图为:使用 RisingWave 进行监控,并实时将结果展示在 Grafana 中。)

总结

RisingWave 的最大特点之一就是简洁:用户可以几乎无门槛的使用 SQL 进行分布式流计算。在性能方面,RisingWave 也远胜于 Apache Flink 等大数据时代的流计算平台。

具体的性能对比报告,大家可以参考之前的文章:《Apache Flink 与 RisingWave:流处理性能报告公开预览版》

关于 RisingWave

RisingWave 是一款分布式 SQL 流处理数据库,旨在帮助用户降低实时应用的的开发成本。作为专为云上分布式流处理而设计的系统,RisingWave 为用户提供了与 PostgreSQL 类似的使用体验,并且具备比 Flink 高出 10 倍的性能以及更低的成本。了解更多:

GitHub: risingwave.com/github

官网: risingwave.com

公众号: RisingWave 中文开源社区

相关推荐
2401_8576226616 分钟前
SpringBoot框架下校园资料库的构建与优化
spring boot·后端·php
正小安19 分钟前
如何在微信小程序中实现分包加载和预下载
前端·微信小程序·小程序
2402_8575893620 分钟前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
哎呦没1 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
_.Switch2 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
一路向前的月光2 小时前
Vue2中的监听和计算属性的区别
前端·javascript·vue.js
长路 ㅤ   2 小时前
vite学习教程06、vite.config.js配置
前端·vite配置·端口设置·本地开发
长路 ㅤ   2 小时前
vue-live2d看板娘集成方案设计使用教程
前端·javascript·vue.js·live2d
Fan_web2 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
安冬的码畜日常2 小时前
【CSS in Depth 2 精译_044】第七章 响应式设计概述
前端·css·css3·html5·响应式设计·响应式