2. 核心概念扫盲
好,咱们正式开始啃硬骨头了。
这一章,我把流批一体里最绕人的四组概念拎出来,掰开揉碎讲清楚。你可能会觉得这些词儿听着耳熟,但真让你说区别,又有点含糊。没关系,我当年也是这样。
我记得刚接触大数据那会儿,被「流处理」和「批处理」这两个词搞得晕头转向。后来在项目里踩了坑,才真正明白它们到底在说什么。今天我就用最直白的话,把这四组概念给你讲透。
1. 有界数据 vs 无界数据:数据到底有没有尽头?
这是最基础的一对概念。说白了,就是看数据有没有「终点」。
一句话总结:有界数据是「已知全集」,无界数据是「持续追加」。
有界数据(Bounded Data),就是数据量是固定的、已知的。比如你跑一个 Hive 任务,处理昨天的日志文件。昨天的日志就那么多,不会突然多出来一条。处理完就完事了。
无界数据(Unbounded Data),就是数据源源不断地产生,没有尽头。比如用户点击流、传感器数据、交易流水。你永远不知道下一秒会来多少条。
我在项目中遇到过一个问题:有个同事把 Kafka 里的实时数据当成有界数据来处理,写了个批处理脚本每小时跑一次。结果数据延迟越来越大,因为数据一直在产生,而他的脚本永远追不上。嗯,这就是没搞清楚数据边界。
| 维度 | 有界数据 | 无界数据 |
|---|---|---|
| 数据量 | 固定、已知 | 无限、未知 |
| 处理方式 | 一次性全量处理 | 持续增量处理 |
| 典型场景 | 离线报表、历史分析 | 实时监控、在线推荐 |
| 存储系统 | HDFS、Hive 表 | Kafka、Kinesis |
2. 批处理 vs 流处理:两种不同的干活方式
搞清楚了数据边界,再来看处理方式就简单了。
批处理(Batch Processing),就是「攒够了再干」。把一批数据收集起来,一次性处理完。优点是吞吐量大,缺点是延迟高。你想想看,如果银行每天凌晨才结算当天的交易,那白天你查余额时看到的其实是昨天的数据。
流处理(Stream Processing),就是「来一条干一条」。数据一到就立刻处理,延迟极低。但吞吐量相对小,而且处理逻辑更复杂。比如风控系统,用户刚点了一下支付,系统必须在几百毫秒内判断这笔交易有没有风险。
我的经验:别把批处理和流处理对立起来。在实际项目中,往往是「流批协同」。比如用流处理做实时告警,用批处理做离线报表。两者各有各的用处。
我曾经在一个电商项目中,把订单数据的实时统计和离线对账分开做。实时统计用 Flink,延迟控制在秒级;离线对账用 Spark,每天凌晨跑一次。这样既保证了实时性,又保证了准确性。
| 维度 | 批处理 | 流处理 |
|---|---|---|
| 数据范围 | 有界数据 | 无界数据 |
| 延迟 | 分钟~小时级 | 毫秒~秒级 |
| 吞吐量 | 高 | 相对低 |
| 计算模型 | MapReduce、Spark | Flink、Storm |
| 典型场景 | 离线报表、数据清洗 | 实时监控、在线推荐 |
3. 实时性 vs 准确性:鱼和熊掌怎么兼得?
这是流批一体里最让人头疼的一对矛盾。
实时性,就是数据从产生到被处理,中间的时间差有多短。你希望越快越好,最好毫秒级。
准确性,就是处理结果和真实情况有多接近。你希望越准越好,最好 100% 精确。
但问题是,这两者往往互相冲突。为什么?
你想想看,如果数据有延迟到达(比如网络抖动),你是等它到了再处理,还是先处理已有的数据?等,准确性高,但实时性差;不等,实时性好,但结果可能不准确。
避坑指南:我曾经在一个实时大屏项目里,为了追求毫秒级刷新,直接忽略了迟到的数据。结果大屏上的数字和数据库里的对不上,被业务方追着问。后来我加了迟到数据处理机制,虽然延迟多了几百毫秒,但数据终于对得上了。
流批一体框架(比如 Flink)提供了一些折中方案:
- 事件时间 + Watermark:允许数据迟到一定时间,超过这个时间就不再等待。
- 允许迟到数据:迟到的数据可以触发一次额外的计算,更新之前的结果。
- 端到端一致性:通过 Checkpoint 和 Exactly-Once 语义,保证最终结果准确。
说白了,没有的「实时」和「准确」,只有「在可接受的范围内,找到平衡点」。
4. 事件时间 vs 处理时间:时间到底听谁的?
这是流处理里最容易搞混的概念。我刚开始学的时候,也绕了很久。
事件时间(Event Time),就是数据实际发生的时间。比如用户点击按钮的那一刻,手机上的时间戳。
处理时间(Processing Time),就是数据被系统处理的时间。比如 Flink 任务收到这条数据的那一刻,服务器上的时间戳。
为什么这两个时间不一样?因为数据在传输过程中会有延迟。用户点击按钮是 10:00:00,但数据因为网络拥堵,10:00:05 才到达 Flink。那么事件时间是 10:00:00,处理时间是 10:00:05。
核心原则:做流处理时,尽量用事件时间。因为处理时间会受系统负载、网络延迟等因素影响,结果不可复现。而事件时间是数据本身的属性,不管什么时候处理,结果都一样。
我记得有一次,一个同事用处理时间做窗口聚合。结果每次跑出来的结果都不一样,因为每次数据到达的时间不同。后来改成事件时间,结果就稳定了。
当然,用事件时间也有代价:你需要处理迟到数据。这就引出了 Watermark 的概念——我们会在后面的章节详细讲。
| 维度 | 事件时间 | 处理时间 |
|---|---|---|
| 定义 | 数据产生的时间 | 数据被处理的时间 |
| 确定性 | 确定,不会变 | 不确定,每次可能不同 |
| 依赖 | 数据本身的时间戳 | 系统时钟 |
| 优点 | 结果可复现,准确 | 延迟低,实现简单 |
| 缺点 | 需要处理迟到数据 | 结果不稳定,不准确 |
| 推荐场景 | 需要精确统计的场景 | 对准确性要求不高的场景 |
5. 四组概念的关系:一张图看懂
说了这么多,你可能有点晕。没关系,我画了一张图,把这四组概念串起来。
从这张图可以看得很清楚:
- 数据边界决定了你用什么处理方式。有界数据适合批处理,无界数据适合流处理。
- 流处理中,你会遇到实时性 vs 准确性的矛盾,以及事件时间 vs 处理时间的选择。
- 最终,流批一体框架(比如 Flink)提供了统一的解决方案,让你既能处理有界数据,也能处理无界数据,还能在实时性和准确性之间找到平衡。
我的建议:刚开始学的时候,别急着把所有概念都搞透。先记住「有界数据用批处理,无界数据用流处理」这个基本原则。后面用到具体技术时,再回头来理解这些概念,会更容易。
好了,这一章的核心概念就讲到这里。你可能会觉得信息量有点大,没关系,后面每一章都会用到这些概念,慢慢就熟悉了。