我正在开发 DocFlow,它是一个完整的 AI 全栈协同文档平台。该项目融合了多个技术栈,包括基于
Tiptap的富文本编辑器、NestJs后端服务、AI集成功能和实时协作。在开发过程中,我积累了丰富的实战经验,涵盖了Tiptap的深度定制、性能优化和协作功能的实现等核心难点。
如果你对 AI 全栈开发、Tiptap 富文本编辑器定制或 DocFlow 项目的完整技术方案感兴趣,欢迎加我微信 yunmz777 进行私聊咨询,获取详细的技术分享和最佳实践。
我们经常看到数据平台把 Kafka、Flink 和 ClickHouse 组合在一起。下面聊聊这种组合在什么场景下合适、什么时候算过度设计,以及边界在哪里。本文会依次展开三块内容:为什么是这三件套、它们适合用在哪些业务场景、什么时候其实不必上全栈;最后给一条可操作的选型与落地建议。
从 Lambda、Kappa 到 KFC
Lambda、Kappa 这类数据平台架构模式,是为了应对大规模数据处理,并在流式分析与数据湖历史查询之间搭桥。Lambda 用并行的批处理层和速度层,模型可行,但带来重复代码路径和持续对账。Kappa 则把(不可变的)Kafka 事件日志当作唯一事实来源,所有处理都走流式框架,从而做了简化,这个思路也是后来诞生 Flink 的催化剂。
随着数据量增长、数据技术在生产环境里成熟,架构不断演进,往往也超出了这些抽象模式。过去几年里,我们在不同行业里看到一种组合反复出现,既有我们从头设计的系统,也有被叫去优化的既有平台,我们把它叫做 "KFC 架构蓝图":Kafka、Flink、ClickHouse。
三种技术各自在自家领域占优,组合起来形成从接入、转换到亚秒级分析查询的端到端实时数据处理方案。与其说是抽象架构,不如说是一套具体的技术选型蓝图;用对场景时,能明显改变一家公司对分析平台的做法,用错场景时,也可能变成维护和排障的"黑洞"。
为什么是 Kafka、Flink、ClickHouse
栈里每个组件解决一类问题,技术本身久经考验、在生产里大规模验证过,三者又能很好地衔接和互补。
Kafka 充当事件流骨干。其基于日志、只追加的架构提供可配置保留期的持久、有序事件存储。生产者和消费者完全解耦、易于水平扩展,数据源写事件时不必知道谁在消费,消费者可以按自己的节奏处理,也可以回放历史。Kafka 在栈里的角色就是,接收来自各处的数据,持久存储,并让任意多个下游消费者可用。
Flink 负责有状态的流处理,也就是原始事件接入与分析存储之间的那一层逻辑。它可以按事件时间或到达时间处理,能处理迟到和乱序数据,并在海量键上维护分布式状态。其 checkpoint 机制支持精确恢复到故障点且不丢数据;配合 Kafka 的两阶段提交流程,Flink 能提供端到端恰好一次语义,这对金融交易、计费、反欺诈等是硬需求。窗口连接、会话化、复杂事件处理、多流富化,才是 Flink 真正擅长的场景。
ClickHouse 是管道末端的高性能分析存储,也是近年来分析库里的"新星"。列式存储和向量化查询执行,让它在数据仓库和实时分析场景下都有出色的性能与成本表现。MergeTree 引擎族针对不同访问模式提供多种变体:ReplacingMergeTree 做去重、AggregatingMergeTree 做预聚合、SummingMergeTree 做自动汇总。ClickHouse 通常在数十亿行规模下做到亚秒级查询延迟,既适合内部看板,也适合面向用户的分析产品。
在一个 KFC 平台里,数据流清晰且针对性强,整体如下。
数据源把事件写入 Kafka 的 topic,Flink 消费并做转换(流连接、记录富化、聚合计算、过滤噪音,有时还会触发额外动作),然后把结果写入 ClickHouse;分析师和应用在 ClickHouse 上对处理后的数据做亚秒级查询。
KFC 蓝图适合用在哪儿
KFC 模式特别适合对数据新鲜度、可靠性和成本有严格要求的大规模数据平台,也就是高吞吐事件接入、实时处理和快速分析需要同时满足的场景。典型例子如下。
实时反欺诈很自然。支付系统把交易事件写入 Kafka,Flink 做窗口模式检测(频次检查、地理异常打分、在线 ML 模型推理等)并用用户画像富化事件,被标记的交易落入 ClickHouse,分析师在数十亿行上查欺诈团伙、调规则、建看板。ClickHouse 也可以作为"实时记忆"的在线层,做亚秒级记录关联。
点击流与产品分析类产品形态类似。Web 和移动端事件经 Kafka 进入,Flink 对原始点击流做会话化(按无活动间隔把事件归成用户会话)、计算参与度指标、做跨设备身份解析。ClickHouse 存会话化后的数据,支撑按 cohort、地域或功能开关下钻的分析看板,例如"你的每周收听报告"或内部产品指标。
物联网与车队遥测则受益于 Flink 在时序降采样和异常检测上的规模化能力。传感器高频数据进 Kafka,Flink 做降采样和告警,ClickHouse 存处理后的时序,支撑按路线平均油耗、数千边缘设备 P99 延迟等聚合查询。实时广告分析需要归因窗口内的多流连接和去重(曝光、点击、转化)。金融市场数据需要实时计算 VWAP、移动平均、订单簿信号,并把 tick 级数据存下来做回测和合规报表。
共性在于:Kafka 解耦生产与消费并保证持久化;Flink 承担有状态、对时间敏感、用简单消费者难以表达的复杂逻辑(连接、窗口、恰好一次语义);ClickHouse 在传统 OLTP 数据库难以胜任的规模下提供亚秒级分析查询。只要同时需要实时处理和大体量事件数据的快速历史分析,这套栈就适用。
什么时候不该用 KFC
坦白说,很多团队会默认上 "Kafka → Flink → ClickHouse" 架构,而更简单的方案往往就能覆盖八成需求、运维成本低得多。Flink 无疑会带来实实在在的运维复杂度:checkpoint 调优、状态后端管理、作业升级、背压处理。这些复杂度必须有对应的业务需求来支撑。
简单管道就够用的时候
如果工作负载本质是"把原始或轻度转换的事件落进 ClickHouse 再查",其实用不到 Flink。ClickHouse 的 Kafka 表引擎可以直接从 Kafka topic 消费,再配合物化视图,在写入时做过滤、列提取、轻度聚合等简单转换。例如 Mux 用级联物化视图和 Null 表替代了整个 Flink 层,实现了约 50 万写/秒、消费延迟在一分钟以内。
其他选择还有:Kafka Connect 配 ClickHouse sink 连接器、ClickHouse Cloud 上的 ClickPipes 托管接入,以及 Vector、Airflow 或自写消费者。Cloudflare 用 106 个 Go 消费者批量写入 ClickHouse,每秒处理约 600 万 HTTP 请求,整条链路上没有 Flink。
建议先上简单方案,只有在碰到明确瓶颈时再引入 Flink。KFC 里的 F 有时也可以理解为 Friction(摩擦)。
什么时候才真的需要 Flink
边界可以这样判断:
- 跨流的窗口连接:例如在 30 分钟归因窗口内把点击和曝光做连接,或用最新库存快照富化订单并近实时响应,这类需求要在事件上维护跨时间状态。
- 复杂事件处理(CEP):检测诸如"5 分钟内三次登录失败后从不同 IP 发起密码重置"这类序列。
- 会话化:按无活动间隔把原始点击流聚成会话,本身就有状态,往往难以用物化视图表达。
- 带副作用的恰好一次语义:在处理过程中触发告警、调外部 API,或原子地写入多个 sink。
- 超大规模预聚合:通过有状态的窗口与回撤逻辑,在进 ClickHouse 前把写入量降几个数量级。ClickHouse 写入性能很强,但在某些规模下,在流上先做过滤、采样或汇总会更划算。
- 多 sink 路由:一次处理,同时写入 ClickHouse、S3、另一个 Kafka topic 和缓存,并配合协调的 checkpoint。
如果以上都不沾边,大概率不需要 Flink。可以自问两句:"我是否需要在事件之间维护状态?" 以及 "我是否需要在时间维度上连接多条流?" 若答案是肯定的,再上 Flink;否则交给 ClickHouse 即可。下面这张图概括了"先简单、再按需加 Flink"的决策思路。
小结与落地建议
KFC 架构蓝图之所以成立,是因为每个组件只做好自己的事:Kafka 负责接入和解耦,Flink 负责有状态流处理,ClickHouse 负责分析查询。边界清晰,且每项技术都在 Cloudflare、eBay、Uber、Lyft 等公司的规模下久经考验。
但全栈并不总是正确选择。很多分析负载只需要 Kafka 和 ClickHouse,用物化视图做转换就够了。运行 Flink 的运维成本(checkpoint 调优、状态管理、集群规模)需要和实际处理需求权衡。
建议的路径是:先用 Kafka 直接喂 ClickHouse;当出现 ClickHouse 在写入时处理无法满足的需求(有状态连接、复杂窗口、恰好一次投递)时,再引入 Flink,而不是提前上。