1. 流处理基础与挑战:实时流处理概念、高吞吐场景定义、三大核心挑战

各位同学,咱们今天聊聊流处理。说实话,我入行那会儿,批处理还是的主流。大家跑个 MapReduce 作业,等个十几分钟出结果,都觉得挺正常。直到后来,业务方开始跟我说:「数据能不能秒级看到?」「延迟能不能降到 100 毫秒以内?」——嗯,从那一刻起,流处理就成了绕不开的话题。

这一章,咱们先把地基打牢。搞清楚什么是实时流处理,什么场景算高吞吐,以及我们到底在跟哪三个「拦路虎」较劲。

1.1 什么是实时流处理?

简单说,数据是一条一条、源源不断过来的。你没法等所有数据到齐了再算,必须来一条处理一条,或者来一批处理一批。这就是流处理。

我习惯把流处理比作「流水线上的质检员」。零件(数据)从传送带上过来,质检员(算子)看一眼,合格的放行,不合格的挑出来,偶尔还要统计一下今天的次品率。你不能等所有零件都生产完了再开始检查,对吧?

流处理的核心特征就三个:

  • 无界数据:数据是无限的,你不知道什么时候结束。
  • 持续计算:计算引擎 7×24 小时跑着,从不关机。
  • 低延迟:从数据产生到结果输出,通常要求在秒级甚至毫秒级。

关键认知:流处理不是批处理的「阉割版」,而是一种全新的计算范式。批处理追求「全量准确」,流处理追求「持续低延迟下的近似准确」。两者各有各的战场。

1.2 高吞吐场景到底长什么样?

你想想看,什么样的场景才算「高吞吐」?

我个人有个简单的判断标准:单节点每秒处理的消息量超过 10 万条,或者集群整体吞吐超过百万级 QPS。这时候,常规的优化手段就开始失效了。

我在项目中遇到过几个典型的高吞吐场景:

  • 电商大促实时风控:双十一期间,每秒要分析几十万笔交易,判断有没有盗刷风险。延迟超过 200 毫秒,用户可能就下单失败了。
  • 物联网设备数据采集:几百万台设备同时上报温度、湿度、电压。数据量不大,但频率极高,每秒几百万条。
  • 广告实时计费:用户点一下广告,系统要在几十毫秒内完成曝光记录、点击扣费、预算扣减。少扣了亏钱,多扣了被投诉。
场景 典型吞吐量 延迟要求 容错代价
电商风控 50-200 万条/秒 < 200ms 极高(误判=真金白银)
物联网采集 100-500 万条/秒 < 1s 中等(丢几条可接受)
广告计费 10-50 万条/秒 < 50ms 极高(不能多扣不能少扣)

我的经验:高吞吐场景下,瓶颈往往不在 CPU,而在网络 IO 和序列化/反序列化。你写一个高效的算子,可能还不如把 Protobuf 换成 FlatBuffers 来得实在。

1.3 三大核心挑战:延迟、吞吐、容错

做流处理,说白了就是在跟三个东西较劲:延迟(Latency)、吞吐(Throughput)、容错(Fault Tolerance)。这三者之间,存在一个经典的「不可能三角」。

为什么会这样?我给你画张图就明白了。

流处理三大核心挑战:不可能三角 延迟 吞吐 容错 三者互相制约:降低延迟通常牺牲吞吐,提升容错往往增加延迟,追求高吞吐又可能弱化容错 延迟 数据从产生到结果输出的时间 典型目标:毫秒级 ~ 秒级 影响因素:网络、序列化、算子复杂度 吞吐 单位时间内能处理的数据量 典型目标:10万+ 条/秒/节点 影响因素:并行度、资源分配、背压 容错 系统故障后能否恢复且保证数据不丢不重 典型方案:检查点(Checkpoint)、至少一次/精确一次语义 影响因素:状态大小、快照频率、恢复时间

1.3.1 延迟:用户等不起

延迟是流处理的第一道坎。用户点了个按钮,3 秒后还没看到结果,他可能就关页面了。

延迟的来源主要有三个:

  1. 网络传输:数据从源头到计算节点,中间经过多少跳?有没有跨机房?
  2. 序列化/反序列化:每处理一条数据,都要把二进制转成对象,算完再转回去。这个开销比你想象的大得多。
  3. 算子处理逻辑:你的业务逻辑有多复杂?是简单的过滤,还是需要做窗口聚合、关联维表?

避坑指南:我曾经在一个项目中,为了降低延迟,把检查点间隔从 1 分钟调到了 10 秒。结果延迟是降下来了,但系统频繁触发全量快照,CPU 被打满,吞吐直接腰斩。后来我才明白,延迟和容错之间必须找到平衡点,不能顾此失彼。

1.3.2 吞吐:数据量扛不住

吞吐是流处理的第二道坎。数据量上来了,系统能不能撑住?

影响吞吐的核心因素:

  • 并行度:一个算子能不能拆成多个子任务并行跑?并行度越高,吞吐越大,但资源消耗也越大。
  • 背压(Backpressure):下游处理不过来,上游还在拼命发数据,怎么办?没有背压机制,系统直接 OOM。
  • 资源分配:CPU、内存、网络带宽,哪个先到瓶颈?

你想想看,如果每秒来 100 万条数据,你的算子处理一条要 1 毫秒,那单线程最多处理 1000 条/秒。怎么办?只能加并行度,拆成 1000 个线程并行跑。但线程多了,上下文切换的开销又上来了。这就是典型的「吞吐与延迟的博弈」。

1.3.3 容错:挂了怎么办?

容错是流处理的第三道坎,也是最容易被忽视的。系统跑着跑着挂了,重启之后数据怎么恢复?

容错的核心问题就两个:

  • 状态一致性:挂了之后,状态是丢了、重复了,还是精确一次?
  • 恢复速度:从故障中恢复需要多久?如果恢复要 10 分钟,那延迟再低也没用。

常见的容错方案:

方案 一致性语义 恢复时间 对吞吐的影响
至少一次(At-Least-Once) 数据可能重复 快 小
精确一次(Exactly-Once) 数据不丢不重 中等 中
端到端精确一次 从源头到 sink 完全一致 慢 大

我的建议:不要一开始就追求「端到端精确一次」。先搞清楚业务到底能不能接受少量重复。很多场景下,「至少一次」加上下游去重,比「精确一次」性价比高得多。

1.4 本章小结

好了,这一章咱们把流处理的基础和挑战捋了一遍。记住三个关键词:无界数据、持续计算、低延迟。记住三个挑战:延迟、吞吐、容错。这三者之间互相制约,没有银弹。

后面的课程,我会带着大家一步步拆解这些挑战。从数据源优化、算子调优、状态管理,到背压处理、资源调度,每一个环节都有坑,也都有解法。