Skip to content

计算与接入选型 ​

链路分工 ​

环节组件职责不负责什么
变更捕获Flink CDC读 MySQL/PG 的 binlog,写 Kafka不做复杂清洗
批量接入DataX全量/增量抽数,写 Iceberg 或 Kafka不做常驻服务
缓冲Kafka削峰、解耦、可重放不做长期存储
流处理Flink实时清洗、聚合、入湖不做 T+1 全量重算
批处理Spark全量重算、历史回溯、T+1 报表不做秒级查询
调度DolphinScheduler依赖编排、重跑、补数不做计算

一、Kafka:为什么不能省 ​

实时链路的三件事——削峰、解耦、可重放——都需要一个消息层:

  • 业务库晚高峰的 binlog 洪峰不能直接打到湖上;
  • 入湖任务升级、重启时,数据不能丢;
  • 算错了要能回到某个位点重算。

部署形态 ​

项生产3 节点测试
模式KRaft(不再依赖 ZK)KRaft
Broker 数≥33
副本因子33
min.insync.replicas22
保留按业务 3–7 天1 天
存储独立数据盘PVC

落地要点 ​

  1. 分区数不是越多越好:按峰值吞吐估,单分区 5–10 MB/s;分区过多会拖垮控制器和 Flink 的 checkpoint。
  2. Key 决定顺序:同一业务主键必须同 key,否则下游乱序。
  3. 别把 Kafka 当数据库:保留时间到了就删,长期存储是 Iceberg 的事。
  4. 监控 lag:消费者 lag 是最重要的指标,比 broker CPU 更能说明问题。

二、Doris:为什么是它 ​

候选对比 ​

维度DorisStarRocksClickHouseGreenplum
架构形态MPP + 存算分离,多计算集群共享同一份对象存储数据MPP,存算分离版本较新单表扫描极快,多表关联弱传统 MPP,扩容成本高
接入协议兼容 MySQL 协议,现有 BI 工具只改连接串兼容 MySQL 协议自有协议,BI 侧需适配PostgreSQL 协议
湖上查询外部表经 Catalog 直读 Iceberg,热点表再同步本地副本支持外部表能力较弱不支持湖上直读
并发与更新高并发点查 + 主键表更新高并发强,更新能力相近点查弱,更新代价高并发能力受限
运维与扩容单一体架构,组件少、参数少,加节点即扩容架构相近,社区迭代较快合并策略与参数调优负担重需专职 DBA
许可Apache-2.0Apache-2.0Apache-2.0社区版已停更

结论 ​

Doris 综合最均衡:

  • MySQL 协议意味着现有 BI 工具只改一个连接串,接入成本最低;
  • 存算分离让"看板查询"和"重算任务"用不同计算集群,互不抢资源;
  • 主键表能承接 CDC 的更新,明细核对不用回湖里查。

StarRocks 作为压测对照备选——两者同源,能力接近,最终用 Benchmark 说话,不靠感觉。

注意:Doris 里存的是热点副本,不是事实源。任何"只存在 Doris 里"的数据,都违反了第一原则。

落地要点 ​

  1. 表模型:明细用 Duplicate,需要更新的用 Unique(Merge-on-Write),聚合报表用 Aggregate。
  2. 分区与分桶:按天分区,分桶数 ≈ BE 数 × 2–4,别拍脑袋。
  3. 外表:Iceberg 外表用于低频/全量查询;高频看板才同步成本地表。
  4. 资源组:把 ETL 写入和 BI 查询分到不同资源组,避免互相拖垮。
  5. 测试取舍:3 节点可以跑 3 FE + 3 BE,验证副本与选主;只想先跑通就 1 FE + 3 BE,但验证不了 FE 选主。存算分离需要共享存储与 Meta Service,测试期先用存算一体,别把两件事混在一起调。

三、Elasticsearch:只做索引 ​

定位:OpenMetadata 的搜索后端,让人能在 UI 里搜表、搜字段、搜血缘。仅此而已。

三条红线:

  1. 不承担业务全文检索;
  2. 不承担日志检索(日志走 Loki);
  3. 不作为任何数据的唯一存储——删掉 ES,元数据仍在 PostgreSQL,重建索引即可。

许可提醒:Elasticsearch 是 AGPLv3 / SSPL / Elastic License 三选一。内部使用没问题;如果整套平台要交付给客户,改用 OpenSearch(Apache-2.0) 更省事。

  • Flink CDC 能直接读 MySQL/PG 的 binlog,不用额外部署 Canal/Debezium 集群;
  • 流批一体,实时入湖和离线修正用同一套 SQL;
  • K8s Operator 成熟,TaskManager 可以按需伸缩。

链路设计 ​

MySQL ──binlog──► Flink CDC Source ──► Kafka(原始变更) ──► Flink SQL(清洗/打宽) ──► Iceberg

为什么 CDC 先写 Kafka 再入湖,而不是直接写湖?

  • 任何一段失败(Flink 重启、湖写入限流)都不会丢数据,Kafka 里有原始变更可重放;
  • 多个下游(实时指标、入湖、审计)可以各自消费,互不影响;
  • 业务库的变更速率和湖的写入速率解耦。

落地要点 ​

  1. Checkpoint 存 S3:state.checkpoints.dir=s3://flink/checkpoints,别放本地盘。
  2. Exactly-once:Kafka sink 开两阶段提交;Iceberg sink 用 Flink 的 Iceberg connector,提交依赖 Iceberg 的原子快照。
  3. 水位线:CDC 流是 unbounded,窗口聚合必须定义 watermark,否则状态无限增长。
  4. 反压:看 backpressure 指标,不要只看 CPU;反压通常是下游(Kafka/湖)写入跟不上。
  5. Savepoint:升级作业前先打 savepoint,回滚才有依据。

五、DataX:批量接入 ​

为什么还用它:支持的数据源极多(关系库、文件、Hive、ES、MongoDB……),配置简单,跑完即退,天然无状态。

为什么不用 SeaTunnel 替代:

  • SeaTunnel 的卖点是流批一体,但流处理已经由 Flink 承担,优势被抵消;
  • DataX 是"提交一个 Job,跑完就结束",K8s 管起来很轻;SeaTunnel 常驻服务,多一层运维。

落地要点:

  • DataX 作业打成镜像,用 K8s Job 跑,失败由调度器重试;
  • 限流(speed.byte / record)必须配,否则抽数会把业务库打满;
  • 全量初始化 + 增量按时间戳/自增 ID,增量字段要有索引;
  • 脏数据用 errorLimit 控制,别让一条脏数据卡死整个作业。

六、Spark:批处理主力 ​

没有替代品:全量重算、历史回溯、复杂多表关联、Iceberg 维护(compaction / expire snapshots),都靠 Spark。

部署方式:

  • 生产用 Spark Operator,作业以 SparkApplication CRD 提交,镜像、依赖、资源都声明化;
  • POC 可以直接 spark-submit --master k8s://...,少一层 Operator。

落地要点:

  1. AQE 打开:spark.sql.adaptive.enabled=true,动态合并分区、处理倾斜。
  2. Shuffle 落 S3:spark.shuffle.service.enabled 或 Remote Shuffle Service;本地盘 shuffle 在 K8s 上容易把节点写满。
  3. Iceberg 写优化:控制文件大小(128–256 MB),写前 DISTRIBUTE BY 分区列,减少小文件。
  4. 资源队列:用 K8s 的 ResourceQuota 限制 Spark 命名空间,避免一个大作业吃光集群。

七、DolphinScheduler:调度收口 ​

对比 ​

维度DolphinSchedulerAirflow定时任务平台(cron/XXL-Job)
编排方式可视化拖拽 DAG,业务人员能改以 Python 代码定义 DAG,改流程要改代码发版只能按时间触发,无依赖关系
任务类型内置 Spark / Flink / SQL / Shell / K8s 等需自行封装 Operator只能跑脚本
重跑与补数失败重试、单步重跑、按日历区间补数内置支持,但回填需写脚本无补数概念
多租户与权限内置项目 / 用户 / 租户与资源队列需插件或外置方案无
部署形态原生支持容器化与 K8s可容器化,但常驻组件较多单机
生态Apache 顶级项目,国内使用广Apache-2.0,社区大但偏英文—

更正一个常见说法:Airflow 是有 Web UI 的,它的差异不在"有没有界面",而在 DAG 用代码定义——业务改流程要改代码、发版、评审;DolphinScheduler 是可视化拖拽,运营和数仓自己能改。

结论 ​

DolphinScheduler 在国内生态下集成成本最低:可视化编排、内置主流引擎任务类型、原生容器化、多租户。Airflow 作为备选,适合"平台团队全是 Python 工程师、一切皆代码"的团队。

落地要点 ​

  1. DAG 粒度:一个业务域一个项目,一个主题域一个工作流,别把几百个任务塞一个 DAG。
  2. 补数策略:按日历区间补,任务必须幂等(INSERT OVERWRITE 或按分区覆盖)。
  3. 告警:接 Alertmanager,按级别分流;失败告警要带 DAG、任务、日志链接。
  4. K8s 任务:用 K8s 任务类型直接起 Pod,避免 Worker 上装一堆客户端。

结论 ​

决策点结论备选说明
消息Kafka(KRaft)—实时链路必需
OLAPDorisStarRocks用压测决定最终选型
检索索引ElasticsearchOpenSearch只服务元数据平台
实时接入/计算Flink + Flink CDCDebezium + Kafka ConnectCDC 直读 binlog 更省组件
批量接入DataXSeaTunnel无状态、跑完即退
批处理Spark—全量重算与 Iceberg 维护
调度DolphinSchedulerAirflow可视化、补数、多租户