实时计算基础:离线与实时的本质差异

做数据这行久了,你会发现一个有意思的现象:很多业务方提需求时,张口就要「实时」。但真问起来,他们其实也说不清到底要多实时——是秒级?分钟级?还是小时级?

我个人习惯,在开始任何实时项目前,先跟业务对齐一个核心问题:这个数据晚到 5 分钟,业务会死吗?如果不会,那离线计算可能更合适。如果会,那我们再聊实时。

实时计算 vs 离线计算:一张表说清楚

先看个对比,这是我给团队新人培训时必用的表格。说白了,两者最大的区别就三个字:延迟。

对比维度 离线计算 实时计算
数据处理延迟 分钟级 ~ 天级(T+1 常见) 毫秒级 ~ 秒级
数据触发方式 定时调度(如每天凌晨 2 点跑) 事件驱动(数据一到就处理)
数据量级 海量(TB/PB 级,一次性全量扫描) 流式(单条或微批次,持续不断)
计算模型 Batch(批处理,MapReduce/Spark) Stream(流处理,逐条或微批)
典型场景 月度报表、用户画像全量更新 实时大屏、风控拦截、实时归因
容错机制 重跑整个 Job(成本高但简单) Checkpoint + 状态恢复(复杂但精准)
资源消耗 集中式爆发(跑完释放) 长期占用(7x24 小时常驻)

嗯,这里要注意:实时不等于快。我见过不少团队,把离线任务调度间隔改成 5 分钟,就号称「实时」了。这其实是伪实时,本质还是批处理。真正的实时计算,数据是一条一条流进来的,处理完就输出,没有「等一批凑齐」这个说法。

实时计算的应用场景:不只是大屏

很多人一提到实时计算,第一反应就是「炫酷的大屏」。确实,实时大屏是最直观的应用。但说实话,在我做过的项目中,真正产生业务价值的,往往是那些看不见的后台服务。

我归纳了四个核心场景:

  • 实时归因与效果分析(本课程核心):用户点击广告后,3 秒内完成归因,判断这次点击来自哪个渠道、哪个活动。我在项目中遇到过,归因延迟超过 10 秒,运营同学就没办法及时调整投放策略,钱就白花了。
  • 实时风控与反欺诈:用户登录、下单、支付,每个环节都要毫秒级判断。比如同一 IP 在 1 秒内注册了 10 个账号,必须立刻拦截。
  • 实时监控与告警:服务器 CPU 飙到 90%、接口错误率超过 5%,系统自动告警。这个场景对延迟要求极高,晚 1 分钟可能就是事故。
  • 实时推荐与个性化:用户刚搜了「羽绒服」,下一秒首页就要推荐羽绒服。这背后就是实时计算在更新用户兴趣标签。

核心观点:实时计算的价值不在于「快」,而在于「快带来的决策闭环」。数据产生 → 实时计算 → 业务决策 → 效果反馈,这个闭环越快,业务迭代就越快。

实时计算技术选型:Flink、Spark Streaming、Kafka Streams

选型是个老生常谈的话题。我自己的经验是:没有最好的技术,只有最合适的场景。下面我结合项目经历,聊聊这三个主流框架。

Apache Flink:实时计算的「正统」

Flink 是我目前的主力框架。为什么?因为它天生就是为流处理设计的。Spark Streaming 本质上是微批次,而 Flink 是真正的逐条处理。

我记得第一次用 Flink 做实时归因时,有个场景需要精确一次(Exactly-Once)语义。Flink 的 Checkpoint 机制配合 Kafka,完美解决了数据不丢不重的问题。换做其他框架,我得写一堆补偿逻辑。

Flink 的核心优势:

  • 真正的流处理引擎,延迟低至毫秒级
  • 强大的状态管理(ValueState、MapState 等)
  • 精确一次语义,容错机制成熟
  • Event Time 处理,完美解决乱序问题

个人建议:如果你的场景需要复杂事件处理(CEP)、状态管理、或者对延迟要求极高(毫秒级),直接选 Flink。别犹豫。

Spark Streaming:批处理的「妥协」

Spark Streaming 本质上是将流数据切成微批次(Micro-Batch),然后用 Spark 的批处理引擎去跑。这个设计有好有坏。

好处是:如果你的团队已经用了 Spark 做离线,那 Spark Streaming 的学习成本很低,代码可以复用。坏处是:微批次天然有延迟,批次间隔再短也做不到逐条处理。

我曾经在一个项目里用 Spark Streaming 做实时大屏,批次间隔设了 1 秒。结果业务方反馈大屏数据总是「跳变」,不够平滑。后来换成 Flink,问题就解决了。原因很简单:微批次是「攒一批算一次」,而流处理是「来一条算一条」。

Spark Streaming 适合的场景:

  • 对延迟要求不高(秒级即可)
  • 团队已有 Spark 技术栈
  • 需要同时做批处理和流处理

避坑指南:我曾经在 Spark Streaming 里做过状态管理,需要自己维护外部存储(如 Redis)。一旦任务重启,状态恢复非常麻烦。而 Flink 的状态后端是内置的,重启后自动恢复。如果你对状态一致性要求高,慎用 Spark Streaming。

Kafka Streams:轻量级的「嵌入式」方案

Kafka Streams 是个很有意思的选择。它不是一个独立的计算集群,而是一个 Java 库,可以嵌入到你的应用里。

我有个项目,业务逻辑很简单:从 Kafka 消费用户点击事件,做一次简单的过滤和转换,然后写回 Kafka。如果用 Flink,得搭一套 Flink 集群,运维成本不低。后来我用 Kafka Streams,几十行代码就搞定了,直接嵌在微服务里跑。

Kafka Streams 的优势:

  • 无需独立集群,部署简单
  • 与 Kafka 深度集成,天然支持 Exactly-Once
  • 适合轻量级 ETL 和简单聚合
  • 学习成本低,会 Java 就能上手

但要注意,Kafka Streams 不适合复杂的状态计算和窗口操作。如果你要做 7 天滑动窗口的归因分析,还是老老实实用 Flink。

技术选型决策树

下面这张图是我自己总结的选型逻辑,每次做技术评审时我都会拿出来对照一下。

实时计算技术选型决策树 实时计算需求 延迟要求 < 100ms 延迟要求 1s ~ 5s 简单 ETL / 轻量 Flink(推荐) Flink / Spark Streaming Kafka Streams 考虑因素 状态管理复杂?→ Flink Exactly-Once 必须?→ Flink 考虑因素 已有 Spark 技术栈?→ Spark 需要 CEP/复杂窗口?→ Flink 考虑因素 不想维护集群?→ Kafka Streams 逻辑简单,无状态?→ 选它 总结:复杂状态 + 低延迟 → Flink 简单 ETL + 不想运维 → Kafka Streams

选型总结:我的建议

说了这么多,最后给个直接的建议:

  • 新项目、复杂场景、对延迟敏感:无脑选 Flink。这是目前实时计算的事实标准,社区活跃,生态完善。
  • 已有 Spark 技术栈、对延迟不敏感:可以选 Spark Streaming。但要做好心理准备,未来如果需求变复杂,迁移到 Flink 的成本不低。
  • 轻量级 ETL、不想引入新框架:Kafka Streams 是个好选择。我有个小项目,就用 Kafka Streams 做了实时数据清洗,跑了两年没出过问题。

最后说一句:技术选型不是一锤子买卖。我见过不少团队,一开始选了 Spark Streaming,后来业务要求实时归因,不得不重构成 Flink。所以,选型时要留出未来演进的余地。如果拿不准,选 Flink 大概率不会错。