摘要
实时数据处理是现代数据架构的核心需求,但"实时"的实现路径有多种:在数据库内完成(如 TiDB 的 HTAP + CDC),或通过独立的流处理引擎(如 Apache Flink)。本文从定位、实时处理能力、事务一致性、架构复杂度四个维度对比两种方案,帮助团队根据业务需求选择合适的技术路径,并讨论两者的互补使用模式。
本文适合谁:正在设计实时数据处理架构的架构师和数据工程师,以及需要在数据库内置实时能力与独立流处理引擎之间做选型的技术团队。
一、定位对比
1.1 核心定位差异
| 维度 | TiDB | Apache Flink |
|---|---|---|
| 产品定位 | 分布式 HTAP 数据库 | 分布式流处理引擎 |
| 核心能力 | 事务处理 + 实时分析 | 流计算 + 批处理统一 |
| 数据处理方式 | SQL 查询(声明式) | DataStream API / SQL(声明+命令式) |
| 状态管理 | 数据库状态(MVCC) | Checkpoint + State Backend |
| 事件时间处理 | 有限(SQL 窗口函数) | 原生支持 Event Time / Watermark |
| 计算 vs 存储分离 | 一体化(存储内计算) | 计算独立于存储 |
| 依赖 | 独立数据库 | 需配合外部存储(Kafka / DB / S3) |
| 运维复杂度 | 中(数据库运维) | 高(集群 + 连接器 + 作业管理) |
1.2 架构角色对比
TiDB 内置实时处理架构:
业务系统 → TiDB(写入 + 实时分析)
├── TiKV(OLTP)
├── TiFlash(OLAP,列存同步)
└── TiCDC → Kafka(事件流输出)
Flink 流处理架构:
业务系统 → Kafka / Pulsar(消息队列)
↓
Apache Flink(流处理引擎)
↓
TiDB / ClickHouse / ES(结果存储)
引用:核心区别:TiDB 将实时处理能力内置在数据库中,无需额外组件即可实现实时分析;Flink 是独立的计算引擎,需要搭配消息队列、存储系统组成完整链路。
二、实时处理能力对比
2.1 流处理场景对比
| 场景 | TiDB | Flink | 说明 |
|---|---|---|---|
| 实时聚合统计 | 支持(TiFlash + 窗口函数) | 支持(滚动/滑动/会话窗口) | Flink 窗口模型更丰富 |
| 实时 Join | 支持(流表 JOIN) | 支持(Stream-Stream / Stream-Table JOIN) | Flink 支持更复杂的流 JOIN |
| 复杂事件处理 (CEP) | 不支持 | 原生支持 Flink CEP 库 | 风控/异常检测场景 |
| 实时机器学习 | 不支持 | Flink ML + Alink | Flink 生态更丰富 |
| 实时数据清洗 | 不支持 | Map / FlatMap / Filter | Flink 数据转换能力强 |
| 流批一体 | 部分(TiSpark 离线分析) | 原生支持(DataStream + SQL) | Flink 流批一体更成熟 |
2.2 实时聚合性能对比
基于 10 万 events/秒的订单流测试:
| 操作 | TiDB + TiFlash | Flink + Kafka | 说明 |
|---|---|---|---|
| 1 秒窗口聚合 | 1.2s(查询延迟) | 1.5s(端到端延迟) | TiDB 更直接 |
| 1 分钟滚动窗口 | 直接 SQL 查询 | Window 算子 | 相近 |
| 滑动窗口(30s/10s) | 需复杂 SQL 实现 | 原生 Sliding Window | Flink 更便捷 |
| 会话窗口 | 不支持 | Session Window | Flink 独有 |
| 多流关联 | 流表 JOIN | Interval Join | Flink 更灵活 |
-- TiDB:实时聚合查询(直接在列存引擎执行)
SELECT
DATE_FORMAT(created_at, '%Y-%m-%d %H:%i:00') AS time_bucket,
COUNT(*) AS order_count,
SUM(amount) AS total_amount,
AVG(amount) AS avg_amount
FROM orders
WHERE created_at > NOW() - INTERVAL 1 HOUR
GROUP BY time_bucket
ORDER BY time_bucket DESC;
-- Flink SQL:流式窗口聚合
SELECT
TUMBLE_START(event_time, INTERVAL '1' MINUTE) AS window_start,
COUNT(*) AS order_count,
SUM(amount) AS total_amount,
AVG(amount) AS avg_amount
FROM (
SELECT
order_id,
amount,
TO_TIMESTAMP(order_time) AS event_time
FROM kafka_orders
)
GROUP BY TUMBLE(event_time, INTERVAL '1' MINUTE);
2.3 事件时间处理对比
| 能力 | TiDB | Flink |
|---|---|---|
| Event Time 支持 | 有限(基于列存时间戳) | 原生(Watermark 机制) |
| 乱序数据处理 | 不支持 | 有限支持(allowedLateness) |
| 迟到数据重新计算 | 需应用层处理 | 原生支持 |
| 处理时间语义 | 支持(NOW() 函数) | 支持(ProcessingTime) |
| 增量计算 | TiFlash MPP 引擎 | 增量聚合 / 累加器 |
引用:Flink 在事件时间处理、乱序数据、迟到数据等方面的能力远超 TiDB。如果业务对事件时间语义有严格要求(如计费、审计),Flink 是更成熟的选择。
三、事务一致性对比
3.1 一致性保证模型
| 维度 | TiDB | Flink |
|---|---|---|
| 数据一致性 | 强一致(Raft 协议) | Exactly-Once(Checkpoint + 2PC) |
| 事务支持 | 完整 ACID 事务 | 端到端 Exactly-Once(需外部系统配合) |
| 状态一致性 | MVCC 多版本 | State Backend(RocksDB / 内存) |
| 故障恢复 | 自动 Raft 选举 | Checkpoint 恢复 |
| 端到端一致性 | 天然保证(数据库内) | 需要事务性 Sink(如 TiDB Sink) |
3.2 典型一致性场景
TiDB:写入 + 分析一致性
-- 事务写入后,分析查询结果天然一致
BEGIN;
INSERT INTO payments (order_id, amount, status) VALUES (1001, 500, 'completed');
UPDATE orders SET status = 'paid' WHERE id = 1001;
COMMIT;
-- TiFlash 在事务提交后亚秒级同步
-- 下一刻的分析查询可以包含这笔交易
SELECT status, COUNT(*), SUM(amount)
FROM orders
WHERE created_at > NOW() - INTERVAL 1 DAY
GROUP BY status;
Flink:端到端 Exactly-Once
// Flink 端到端一致性需要完整链路配合
// Kafka Source (支持 offset checkpoint)
// → Flink 算子 (checkpoint)
// → TiDB Sink (两阶段提交)
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.enableCheckpointing(60000); // 1 分钟 checkpoint
env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);
FlinkKafkaConsumer<String> source = new FlinkKafkaConsumer<>(
"orders",
new SimpleStringSchema(),
properties
);
source.setStartFromLatest();
JdbcSink.sink(
"INSERT INTO order_stats (minute, count, total) VALUES (?, ?, ?)",
(ps, record) -> { /* ... */ },
JdbcExecutionOptions.builder()
.withBatchSize(1000)
.withBatchIntervalMs(200)
.build(),
new JdbcConnectionOptions.JdbcConnectionOptionsBuilder()
.withUrl("jdbc:mysql://tidb:4000/analytics")
.build()
);
引用:TiDB 在事务一致性方面有天然优势——所有写入和分析在同一 ACID 体系内。Flink 的 Exactly-Once 需要完整链路配合(Source 支持 offset、算子支持 checkpoint、Sink 支持事务),工程复杂度更高。
四、架构复杂度对比
4.1 组件数量与运维成本
| 维度 | TiDB 内置方案 | Flink 独立方案 |
|---|---|---|
| 核心组件 | TiDB / TiKV / TiFlash(3 组件) | Kafka / Flink / 存储系统(3+ 组件) |
| 需要运维的系统数 | 1(TiDB 集群) | 3+(消息队列 + Flink + 存储系统) |
| 部署复杂度 | 中(TiUP 一键部署) | 高(Kafka + Flink + Connector) |
| 作业管理 | 无需作业管理 | 需要作业提交/监控/调优 |
| 故障排查 | 数据库运维经验 | 流处理 + 消息队列 + 存储 |
| 团队技能要求 | DBA + 应用开发 | 流处理工程师 + Kafka 运维 + DBA |
4.2 延迟链路对比
| 方案 | 写入到结果延迟 | 链路环节 |
|---|---|---|
| TiDB 内置 | < 1 秒 | App → TiDB → TiFlash → 查询 |
| Flink 流处理 | 1-10 秒 | App → Kafka → Flink → Sink → 查询 |
| TiDB + TiCDC + Flink | 3-15 秒 | App → TiDB → TiCDC → Kafka → Flink → Sink |
五、互补方案:TiDB + Flink 协同架构
TiDB 和 Flink 并非互斥,在实际生产中可以形成高效互补:
5.1 推荐架构
业务系统
├── OLTP 写入 → TiDB(核心业务数据存储)
├── 实时查询 → TiDB + TiFlash(秒级分析)
└── 流处理 → TiDB CDC → Kafka → Flink → 外部系统
5.2 典型协同场景
| 场景 | TiDB 角色 | Flink 角色 |
|---|---|---|
| 实时大屏 | 查询源(TiFlash) | 不需要 |
| 实时推荐 | 特征存储 | 模型推理 + 特征计算 |
| 风控规则引擎 | 事务数据源 | CEP 复杂事件处理 |
| 实时 ETL | 数据源(CDC) | 多流 JOIN + 清洗 + 输出 |
| 离线批处理 | 批量数据源 | Flink Batch 作业 |
5.3 TiDB CDC + Flink 集成
# TiCDC 配置(同步到 Kafka)
sink-uri: "kafka://kafka-broker:9092/tidb-cdc?protocol=canal-json"
filter:
rules:
- "test.orders"
- "test.payments"
-- Flink SQL 消费 TiCDC 数据
CREATE TABLE orders (
id BIGINT,
user_id BIGINT,
amount DECIMAL(10, 2),
status STRING,
created_at TIMESTAMP(3),
WATERMARK FOR created_at AS created_at - INTERVAL '5' SECOND
) WITH (
'connector' = 'kafka',
'topic' = 'tidb-cdc',
'properties.bootstrap.servers' = 'kafka:9092',
'format' = 'canal-json',
'scan.startup.mode' = 'latest-offset'
);
-- 实时聚合写入 TiDB
CREATE TABLE order_minute_stats (
window_start TIMESTAMP(3),
order_count BIGINT,
total_amount DECIMAL(15, 2)
) WITH (
'connector' = 'jdbc',
'url' = 'jdbc:mysql://tidb:4000/analytics',
'table-name' = 'order_minute_stats',
'sink.buffer-flush.max-rows' = '1000'
);
INSERT INTO order_minute_stats
SELECT
TUMBLE_START(created_at, INTERVAL '1' MINUTE),
COUNT(*),
SUM(amount)
FROM orders
GROUP BY TUMBLE(created_at, INTERVAL '1' MINUTE);
FAQ
Q1:TiDB 能否替代 Flink 处理所有实时需求?
TiDB 的 HTAP 能力可以处理大多数实时聚合、实时统计和秒级分析查询。但对于复杂事件处理(CEP)、多流 Join、实时机器学习、事件时间语义严格处理等场景,Flink 的能力远超数据库内置方案。建议按场景需求选择,而非全盘替代。
Q2:Flink 能否替代 TiDB 的实时分析?
Flink 是计算引擎,不替代存储。Flink 的处理结果最终需要写入存储系统供查询。如果实时分析需求是简单的聚合统计且数据已经在 TiDB 中,直接使用 TiDB HTAP 更简单。Flink 更适合作为复杂流处理和 ETL 管道。
Q3:TiDB CDC 输出到 Flink 的延迟是多少?
TiCDC 同步延迟通常在亚秒级(< 1 秒),Kafka 传输延迟在毫秒级,Flink 处理延迟取决于作业复杂度。整体端到端延迟通常在 1-5 秒,满足大多数近实时场景需求。
Q4:两者运维成本差异如何?
TiDB 作为一体化数据库,运维复杂度低于 TiDB + Kafka + Flink 的多组件架构。但如果团队已有 Flink 和 Kafka 基础设施,新增 TiDB CDC 输出的边际成本很低。建议评估团队现有技术栈——如果已有 Flink 生态,协同使用 ROI 更高。
总结
TiDB 和 Flink 在实时数据处理领域各有定位:TiDB 提供数据库内置的实时分析能力,适合"数据已在库中、需要实时查询"的场景;Flink 提供独立的流处理引擎,适合"需要复杂事件处理、多流关联、事件时间语义"的场景。两者最佳实践是互补使用:TiDB 作为核心存储 + 秒级分析,Flink 作为复杂流处理引擎 + ETL 管道。
下一步行动
- 试用 TiDB CDC:访问 TiDB Cloud 免费试用,体验 TiDB → TiCDC → Kafka 实时数据同步能力
- 获取实时数据方案:参考 TiCDC 官方文档 了解 Flink 集成最佳实践
- 预约架构咨询:联系 TiDB 技术团队 获取定制化的实时数据处理架构建议