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

yaml 复制代码
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'

启动所有容器:

bash 复制代码
docker-compose up -d

检查运行状态:

bash 复制代码
docker ps

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

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

bash 复制代码
flink-1.18.0/

将以下 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 协议访问,启动容器后通过以下命令连接:

bash 复制代码
mysql -h127.0.0.1 -P8527 -upolardbx_root -p"123456"

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

sql 复制代码
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 并插入数据

sql 复制代码
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 目录:

bash 复制代码
cd flink-1.18.0

启动 Flink 集群:

bash 复制代码
./bin/start-cluster.sh

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

启动 Flink SQL CLI:

bash 复制代码
./bin/sql-client.sh

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

1. 打开 Checkpoint

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

sql 复制代码
-- Flink SQL
SET execution.checkpointing.interval = 3s;

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

sql 复制代码
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

sql 复制代码
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 中落一张"宽表":订单信息 + 商品信息一起写入:

sql 复制代码
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 做 Join,并把结果写入 ES。

sql 复制代码
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. 插入新订单

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

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

2. 更新订单状态

sql 复制代码
-- PolarDB-X
UPDATE orders
SET order_status = true
WHERE order_id = 10004;

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

3. 删除订单

sql 复制代码
-- PolarDB-X
DELETE FROM orders
WHERE order_id = 10004;

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

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

九、清理环境

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

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

bash 复制代码
docker-compose down

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

bash 复制代码
./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 环境。
相关推荐
说私域1 小时前
智能名片链动2+1模式S2B2C商城小程序:构建私域生态“留”量时代的新引擎
大数据·人工智能·小程序
paperxie_xiexuo2 小时前
如何高效完成科研数据的初步分析?深度体验PaperXie AI科研工具中数据分析模块在统计描述、可视化与方法推荐场景下的实际应用表现
大数据·数据库·人工智能·数据分析
武子康3 小时前
大数据-160 Apache Kylin Cube 实战:从建模到构建与查询(含踩坑与优化)
大数据·后端·apache kylin
非著名架构师3 小时前
智慧气象护航:构建陆海空立体交通气象安全保障体系
大数据·人工智能·安全·疾风气象大模型4.0·疾风气象大模型·风光功率预测
夏洛克信徒4 小时前
从 “工具” 到 “代理”:Gemini 3.0 重构 AI 能力边界,开启智能协作新纪元
大数据·人工智能·神经网络
Caitlin_lee_5 小时前
SCAU数据科学与大数据技术导论期末整理(1-3章)
大数据
weixin_456904278 小时前
Git大文件管理与版本回退
大数据·git·elasticsearch