1. 实时数据流处理,到底在解决什么问题
先说个我实际经历的场景。早几年在一家做智能硬件的公司,设备上报的日志走的是批处理:每天凌晨跑一次Spark任务,把头一天的数据算完入库。平时没事,可一旦赶上设备固件升级或者线上故障,当天的数据要第二天才能看到分析结果,运维那边几乎是“睁眼瞎”状态。后来我们把链路换成实时流处理,延迟从“天级”降到“秒级”,故障发现速度提升了不止一个量级。打那以后我就认准了一件事:实时数据流处理不是炫技,它是真能在关键时刻救命的。
所谓实时数据流处理,简单说就是数据从产生到被计算、被消费,整个过程以极低的延迟持续进行。它不像传统批处理那样“攒一批算一批”,而是数据一条条或一批批地流过来,系统一边接收一边处理,像水管一样,进水口和出水口之间永远在流动。
这套技术适合谁?适合所有对数据时效性有要求的场景。比如你在做电商大促时的实时大屏,要看每秒成交额;你在做风控,要实时拦截异常交易;你在做推荐系统,要根据用户当前行为实时刷新推荐结果;你在做IoT,要实时监控设备状态。只要业务方跟你说“这个数据最好秒级能看到”,那就是实时数据流处理的活儿。
这篇文章我会把整套实时数据流处理链路拆开聊,从核心架构、技术选型、关键原理讲到实操代码和踩坑经验。我尽量不写教科书式的废话,说的都是自己在生产环境里验证过的东西,希望给正在调研或正要上车的同学一些参考。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心架构与技术选型思路
2.1 一条完整的实时数据流链路由哪些环节组成
要理解实时数据流处理,先得在脑子里搭一张拓扑图。任何一套实时系统,无论业务多复杂,基本都逃不开四个环节:数据接入、消息缓冲、流式计算、结果落地。
数据接入负责从各种数据源采集数据。这里的数据源千奇百怪:MySQL的binlog、APP的埋点日志、设备的MQTT消息、前端上报的HTTP请求,甚至另一个系统的消息队列。你得用一个统一的客户端或Agent把这些数据拉出来,转换成标准格式,再往后传。
消息缓冲是整个链路的“蓄水池”。为什么需要它?因为数据产生速率和消费速率往往不一致。比如大促瞬间的流量是平时的几十倍,如果让计算引擎直接扛,分分钟被打爆。引入消息队列(最常见的就是Kafka),相当于在中间加了一个大号缓冲池,生产端猛灌的时候水流先进池子,消费端按自己的节奏慢慢处理,不会互相拖累。
流式计算引擎是核心处理单元,负责做真正的计算逻辑:过滤、清洗、聚合、关联、窗口计算、状态管理都在这一层完成。
结果落地则是把处理完的数据输出到下游系统。有人会问,都处理完了直接展示不行吗?大多数场景还真不行。比如实时大屏,你要把聚合后的指标写进Redis或ClickHouse,前端再从那边查;比如实时风控,你要把命中规则的数据写到ES供后续检索;比如实时数仓,最终结果还是要落到HDFS或Iceberg这类存储里供离线分析使用。
这四层像流水线的四个工位,任何一环出问题都会影响整条链路的实时性。所以在设计初期,就要想清楚每个环节的职责边界,不要试图让一个组件把所有事都干了。
2.2 选流式计算引擎,我为什么最终选了Flink而不是Spark Streaming
当前主流的流式计算引擎有三代:第一代是Storm,纯流式,但延迟虽低、吞吐上不去,而且不支持Exactly-Once语义,现在生产环境已经很少见到新项目用了。第二代是Spark Streaming,它本质上还是“微批”思想,把实时数据切成一小段一小段然后按批处理。第二代半的Structured Streaming做的也是微批,除非你开连续处理模式。第三代就是Flink,真正原生的流式计算引擎,数据一来就处理,延迟能做到毫秒级。
我之前最早用的是Spark Streaming,后来迁移到Flink,核心原因有三点。
第一,延迟。Spark Streaming最小批次间隔一般建议设在500ms以上,否则调度开销太大,实际生产环境下1~2秒是常态。而Flink的延迟可以压到几百毫秒甚至更低。在实时数仓场景下,这个差距直接影响下游报表的时效性。
第二,状态管理。实时计算经常要做“累计”类操作,比如统计用户从登录到下单的全链路行为。Flink内置了RocksDB状态后端,状态可以很大,能做增量Checkpoint。Spark Streaming在这块要弱不少,很多场景你得自己维护外部存储来做状态。
第三,SQL支持成熟度。Flink SQL现在可以覆盖80%以上的实时计算场景,窗口聚合、双流JOIN、维表关联都支持得很顺手,甚至能像写数据库SQL一样写实时任务。对于团队来说,这大大降低了上手门槛。
当然,Spark Streaming也不是一无是处。如果你的团队已经熟悉Spark技术栈,且业务对延迟要求不高,用Structured Streaming实现百毫秒到秒级延迟的数据处理也能跑。但如果你从零建设一套实时数据平台,我的建议是直接梭哈Flink,这是目前投入产出比最高的选择。
2.3 Kafka在数据链路中的正确打开方式
链路中间的消息缓冲层,绝大多数团队选Kafka。Kafka的吞吐能力非常惊人,单分区顺序写磁盘,轻松跑到每秒几十万条。但在真实项目里,我发现很多同学用Kafka是有问题的,最典型的就是分区数和并行度的匹配关系没搞清楚。
Kafka的主题分区数决定了这个Topic的最大并行消费度。一个分区的数据只能被同一个消费组里的一个消费者线程消费,所以你如果Topic只有3个分区,下游Flink任务设置10个并行度,那其中有7个并行度会一直空闲。反向同理,Topic有12个分区,下游并行度只有4,那必然有消费者线程要同时消费多个分区。这就是分区数设计的联动关系。
我一般建议:Topic分区数按下游最大并行度来预设,并且要考虑未来半年的数据量增长。比如你现在下游Flink任务并行度是8,数据量还在涨,那就直接设置16个分区,给未来扩容留空间
