增量计算基础:从“全量重跑”到“只算变化的那一点”
大家好,我是老张。今天咱们聊聊增量计算的基础。说实话,我刚入行那会儿,处理数据就一个思路——全量拉取,全量计算。那时候数据量小,跑个批处理也就几分钟的事。直到后来接手了一个日增几亿条日志的实时数仓项目,全量重跑一次要两三个小时,业务方还要求分钟级延迟……嗯,那才真正体会到什么叫“不改不行”。
增量计算,说白了就是:只处理新增或变化的数据,而不是每次都把历史数据翻出来重算一遍。你想想看,如果每天只新增了 1% 的数据,却要重算 100% 的历史,这多浪费资源?
增量计算 vs 全量计算:核心差异在哪?
我习惯用一个比喻来解释:全量计算就像每次考试都重新学一遍整个学期的内容;增量计算则是只复习错题和新知识点。下面这张表把关键差异列清楚了:
| 对比维度 | 全量计算 | 增量计算 |
|---|---|---|
| 处理范围 | 每次读取全部数据源 | 只读取新增/变更的数据 |
| 计算延迟 | 分钟级到小时级(取决于数据量) | 秒级到分钟级 |
| 资源消耗 | 高,每次都需要大量 CPU 和内存 | 低,只处理变化部分 |
| 数据一致性 | 天然强一致(全量重算) | 需要额外机制保证(如状态快照) |
| 适用场景 | 离线报表、数据仓库全量刷新 | 实时数仓、流处理、指标监控 |
| 代码复杂度 | 低,逻辑简单直接 | 高,需要维护状态和增量逻辑 |
我的经验之谈: 别一上来就追求全增量。我见过不少团队,数据量才几百万条就硬上增量架构,结果状态管理搞出一堆 bug。增量计算的优势在数据量达到亿级、延迟要求秒级时才真正体现出来。小数据量用全量,简单可靠,不丢数据。
增量计算的典型场景
增量计算不是银弹,但在下面几个场景里,它几乎是唯一的选择。
1. 实时数仓
实时数仓的核心诉求是“数据产生后尽快可用”。传统离线数仓 T+1 的节奏,在实时推荐、风控、大屏监控等场景下根本行不通。
我记得在做一个电商实时大屏项目时,需要统计每秒钟的订单金额、用户数、商品点击量。如果用全量计算,每次都要扫描过去一整天的订单表,等算完,业务早就凉了。我们最终采用了增量计算方案:
- Kafka 实时采集订单变更日志(CDC)
- Flink 消费这些增量事件,维护一个分钟级的聚合状态
- 每 10 秒输出一次最新的聚合结果
这样,每次只处理几万条新增数据,而不是几亿条历史数据。延迟从小时级降到了秒级。
2. 流处理
流处理本身就是增量计算的典型代表。每条数据到来时,只更新当前的状态,而不是重新计算整个数据流的历史。
举个例子,计算过去 5 分钟的页面 UV。全量做法是:每 5 分钟把过去 5 分钟的日志全部读出来,去重统计。增量做法是:维护一个滑动窗口,新数据进来就加入窗口,旧数据过期就移出窗口,每次只更新窗口内的计数。
避坑指南: 我曾经在 Flink 的滑动窗口上踩过一个坑——窗口长度和滑动步长设置不当,导致状态膨胀。比如窗口 1 小时,滑动 1 秒,那就要维护 3600 个窗口状态。后来我改成用 sessionWindow 或者自定义触发器,才把状态量降下来。所以,增量计算虽然省了计算资源,但状态管理一定要设计好。
3. 指标监控与告警
业务监控系统需要实时计算各种指标:QPS、错误率、响应时间 P99 等。这些指标如果每次都全量重算,监控系统自己就先挂了。
增量计算在这里的典型做法是:
- 维护一个计数器或滑动窗口状态
- 每条新数据到来时,原子性地更新状态
- 定期(如每秒)输出当前状态值
比如计算最近 1 分钟的错误率,只需要维护两个计数器:总请求数和错误请求数。新请求来了,对应计数器加 1;超过 1 分钟的数据,对应计数器减 1。整个过程只涉及两个整数的加减,效率极高。
增量计算的核心逻辑:一张图看懂
下面这张图展示了增量计算的核心流程。我特意把“状态存储”和“增量处理”这两个关键环节标了出来——这也是后面章节会重点展开的内容。
注意: 增量计算不是“只加不减”。很多新手只关注新增数据,忽略了过期数据的清理。比如滑动窗口里的旧数据如果不移除,状态会无限膨胀,最终导致 OOM。我见过一个线上事故,就是因为窗口过期逻辑写错了,状态从几百 MB 涨到几十 GB,直接把 Flink 任务搞挂了。所以,增量计算一定要配套“增量清理”机制。
什么时候该用增量计算?
我个人的判断标准很简单:
- 数据量达到亿级以上,全量重算的时间超过业务容忍的延迟
- 数据变更频繁,每次只有小部分数据发生变化(比如 1%-5%)
- 对延迟敏感,需要秒级或分钟级输出结果
- 有可靠的状态存储,能保证增量计算的中间结果不丢失
如果以上四点满足三点以上,增量计算就是你的菜。如果数据量不大、延迟要求不高,老老实实用全量计算反而更省心。