完整教程:Flink CDC 用 PolarDB-X CDC 实时同步数据到 Elasticsearch

一、准备工作与整体环境

1. 运行环境假设

  • 一台安装了 Docker 的 Linux 或 MacOS 机器;
  • 下载好 Flink 1.18.0,并解压到目录:flink-1.18.0/

2. 使用 Docker Compose 启动依赖组件

我们需要 3 个容器:

  • PolarDB-X:存储 productsorders
  • Elasticsearch 7.6.0:作为 Flink CDC 的 sink;
  • Kibana 7.6.0:可视化 ES 中的数据。

在一个目录下创建 docker-compose.yml

version: '2.1'
services:
polardbx:
image: polardbx/polardb-x:2.0.1
container_name: polardbx
ports:
- "8527:8527"
elasticsearch:
image: 'elastic/elasticsearch:7.6.0'
container_name: elasticsearch
environment:
- cluster.name=docker-cluster
- bootstrap.memory_lock=true
- ES_JAVA_OPTS=-Xms512m -Xmx512m
- discovery.type=single-node
ports:
- '9200:9200'
- '9300:9300'
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
kibana:
image: 'elastic/kibana:7.6.0'
container_name: kibana
ports:
- '5601:5601'
volumes:
- '/var/run/docker.sock:/var/run/docker.sock'

启动所有容器:

docker-compose up -d

检查运行状态:

docker ps

浏览器访问:http://localhost:5601,可以看到 Kibana 正常启动,就说明 ES + Kibana 环境 OK。

二、准备 Flink 与 CDC 所需 JAR

1. 下载并解压 Flink

假设你已经下载好 Flink 1.18.0,并解压到:

flink-1.18.0/

2. 准备 Flink CDC & ES Connector

将以下 JAR 放到 flink-1.18.0/lib/ 目录:

  • flink-sql-connector-mysql-cdc-3.0-SNAPSHOT.jar
  • flink-sql-connector-elasticsearch7-3.0.1-1.17.jar

注意:PolarDB-X 对外兼容 MySQL 协议,所以我们直接用 mysql-cdc 连接器即可,不需要单独的 PolarDB-X connector。

三、在 PolarDB-X 中准备业务表和数据

1. 连接 PolarDB-X

PolarDB-X 默认通过 MySQL 协议访问,启动容器后通过以下命令连接:

mysql -h127.0.0.1 -P8527 -upolardbx_root -p"123456"

2. 创建商品表 products 并插入数据

CREATE TABLE products (
id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description VARCHAR(512)
) AUTO_INCREMENT = 101;
INSERT INTO products
VALUES (default,"scooter","Small 2-wheel scooter"),
(default,"car battery","12V car battery"),
(default,"12-pack drill bits","12-pack of drill bits with sizes ranging from #40 to #3"),
(default,"hammer","12oz carpenter's hammer"),
(default,"hammer","14oz carpenter's hammer"),
(default,"hammer","16oz carpenter's hammer"),
(default,"rocks","box of assorted rocks"),
(default,"jacket","water resistent black wind breaker"),
(default,"spare tire","24 inch spare tire");

3. 创建订单表 orders 并插入数据

CREATE TABLE orders (
order_id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
order_date DATETIME NOT NULL,
customer_name VARCHAR(255) NOT NULL,
price DECIMAL(10, 5) NOT NULL,
product_id INTEGER NOT NULL,
order_status BOOLEAN NOT NULL -- Whether order has been placed
) AUTO_INCREMENT = 10001;
INSERT INTO orders
VALUES (default, '2020-07-30 10:08:22', 'Jark', 50.50, 102, false),
(default, '2020-07-30 10:11:09', 'Sally', 15.00, 105, false),
(default, '2020-07-30 12:00:30', 'Edward', 25.25, 106, false);

这里我们构造的是一个非常典型的电商场景:

  • products 保存商品基础信息;
  • orders 保存订单信息,并通过 product_id 关联商品。

四、启动 Flink 集群与 Flink SQL CLI

进入 Flink 目录:

cd flink-1.18.0

启动 Flink 集群:

./bin/start-cluster.sh

浏览器访问 Flink UI:http://localhost:8081,看到 Web UI 说明集群正常。

启动 Flink SQL CLI:

./bin/sql-client.sh

成功后会看到 Flink SQL Client 的欢迎界面。

五、在 Flink SQL 中创建 CDC 源表与 ES Sink 表

1. 打开 Checkpoint

CDC 场景下需要启用 checkpoint 来保证容错与一致性:

-- Flink SQL
SET execution.checkpointing.interval = 3s;

2. 创建 PolarDB-X 源表:orders(通过 mysql-cdc)

CREATE TABLE orders (
order_id INT,
order_date TIMESTAMP(0),
customer_name STRING,
price DECIMAL(10, 5),
product_id INT,
order_status BOOLEAN,
PRIMARY KEY (order_id) NOT ENFORCED
) WITH (
'connector' = 'mysql-cdc',
'hostname' = '127.0.0.1',
'port' = '8527',
'username' = 'polardbx_root',
'password' = '123456',
'database-name' = 'mydb',
'table-name' = 'orders'
);

关键点:

  • 虽然数据库是 PolarDB-X,但对外兼容 MySQL 协议,所以使用 mysql-cdc
  • database-name = 'mydb':要根据实际库名调整(Demo 中假设是 mydb);
  • PRIMARY KEY (order_id) NOT ENFORCED:用于 Flink 语义上的主键(Upsert),不强制校验。

3. 创建 PolarDB-X 源表:products

CREATE TABLE products (
id INT,
name STRING,
description STRING,
PRIMARY KEY (id) NOT ENFORCED
) WITH (
'connector' = 'mysql-cdc',
'hostname' = '127.0.0.1',
'port' = '8527',
'username' = 'polardbx_root',
'password' = '123456',
'database-name' = 'mydb',
'table-name' = 'products'
);

有了这两个 CDC 源表,Flink 就可以:

  • 启动时读取 orders / products 的历史快照;
  • 后续持续消费 PolarDB-X 的 binlog,接收实时变更。

4. 创建 Elasticsearch Sink 表:enriched_orders

我们希望在 ES 中落一张“宽表”:订单信息 + 商品信息一起写入:

CREATE TABLE enriched_orders (
order_id INT,
order_date TIMESTAMP(0),
customer_name STRING,
price DECIMAL(10, 5),
product_id INT,
order_status BOOLEAN,
product_name STRING,
product_description STRING,
PRIMARY KEY (order_id) NOT ENFORCED
) WITH (
'connector' = 'elasticsearch-7',
'hosts' = 'http://localhost:9200',
'index' = 'enriched_orders'
);

这里会在 Elasticsearch 中创建(或使用)名为 enriched_orders 的索引。

六、用 Flink SQL 实时富化订单并写入 Elasticsearch

接下来就是最核心的一步:用 Flink SQL 做 Join,并把结果写入 ES。

INSERT INTO enriched_orders
SELECT
o.order_id,
o.order_date,
o.customer_name,
o.price,
o.product_id,
o.order_status,
p.name,
p.description
FROM orders AS o
LEFT JOIN products AS p
ON o.product_id = p.id;

提交这条语句后,Flink 会启动一个长期运行的 Streaming Job:

  1. 从 PolarDB-X 捕获 ordersproducts 的快照及增量变更;
  2. product_id = id 做实时 Join;
  3. 把 Join 后的富化结果 Upsert 到 Elasticsearch 中的 enriched_orders 索引。

七、在 Kibana 中查看实时富化后的订单

1. 创建索引模式(Index Pattern)

打开 Kibana:

2. 查看数据

再打开:

选择刚创建的 enriched_orders index pattern,即可看到已经富化好的订单数据:

  • 来自 orders 的字段:order_id / order_date / customer_name / price / product_id / order_status
  • 来自 products 的字段:product_name / product_description

这时你就已经打通了:

PolarDB-X → Flink CDC(mysql-cdc)→ Flink SQL Join → ES → Kibana

八、在 PolarDB-X 中修改数据,验证实时同步效果

接下来我们在 PolarDB-X 中执行几条 DML,观察 Kibana 中的数据变化。

1. 插入新订单

-- PolarDB-X
INSERT INTO orders
VALUES (default, '2020-07-30 15:22:00', 'Jark', 29.71, 104, false);

执行后,可以在 Kibana 中看到多了一条新订单记录,且商品信息会根据 product_id = 104 关联到 products 表里对应商品。

2. 更新订单状态

-- PolarDB-X
UPDATE orders
SET order_status = true
WHERE order_id = 10004;

刷新 Kibana 的 Discover 页面,会发现对应订单的 order_status 字段变成了 true

3. 删除订单

-- PolarDB-X
DELETE FROM orders
WHERE order_id = 10004;

再次回到 Kibana,order_id = 10004 的记录已经从索引中消失(或被标记删除,取决于具体 ES connector 配置)。

整个过程不需要重启 Job,所有变化都在几乎实时地向下游同步。

九、清理环境

实验结束后,记得清理资源。

关闭 Docker 中的 PolarDB-X / ES / Kibana:

docker-compose down

关闭 Flink 集群(在 flink-1.18.0 目录下):

./bin/stop-cluster.sh

十、小结与扩展思路

本篇我们完成了一条完整的链路:

PolarDB-X(存储 orders/products)
→ 通过 mysql-cdc 捕获变更
→ 在 Flink SQL 中做流式 Join
→ 将富化后的订单写入 Elasticsearch enriched_orders 索引
→ 使用 Kibana 实时查看数据变化

在此基础上,你可以继续扩展:

  • 换成真实业务库 & 表结构(工资、日志、订单、客户等);
  • 在 Flink SQL 中增加过滤、字段清洗、业务衍生字段(如订单状态枚举、货币转换等);
  • 把下游从 ES 换成 Doris / StarRocks / Kafka / ClickHouse 等组件;
  • 把本地 Docker + Standalone Flink 的实验方案迁移到生产 K8s / Yarn 环境。
posted @ 2025-12-17 20:59  clnchanpin  阅读(66)  评论(0)    收藏  举报