1、增量计算概述

大家好,我是这次课程的主讲。今天咱们聊聊增量计算——这个在实时数据处理领域绕不开的核心概念。

说实话,我最早接触增量计算是在做实时数仓的时候。那时候每天要处理几十亿条用户行为日志,全量跑一次要几个小时,业务方还嫌不够快。后来我换了个思路:既然每天变化的数据只有5%,为什么非要重算那95%呢?这就是增量计算的朴素想法。

什么是增量计算

增量计算,说白了就是「只算变化的部分」。

举个例子。你有一张订单表,昨天有100万条记录。今天新增了1万条,修改了2000条。全量计算会把102.2万条全部重算一遍;增量计算只处理那1.2万条变化的数据。

我个人习惯把增量计算拆成三个要素:

  • 变化捕获——怎么知道哪些数据变了?
  • 变化传递——变化的数据怎么流到计算引擎?
  • 状态合并——新结果怎么跟旧结果合并?

这三个要素缺一不可。我在项目中遇到过不少团队,只做了前两步,结果状态合并没处理好,数据对不上,最后还得全量重跑——嗯,这就尴尬了。

核心要点:增量计算不是简单的「只算新增数据」,而是「识别变化 → 传递变化 → 合并状态」的完整链路。

全量计算 vs 增量计算

咱们直接看对比,这样更直观。

对比维度 全量计算 增量计算
计算范围 全部数据 变化的数据
延迟 分钟~小时级 秒级~毫秒级
资源消耗 高(CPU/内存/IO) 低(通常只有全量的5%~20%)
数据一致性 天然一致(全量重算) 需要额外保证(乱序、重复、延迟)
实现复杂度 低(直接SQL即可) 高(需要状态管理、Exactly-Once语义)
适用场景 离线报表、数据快照、数据恢复 实时监控、实时数仓、CDC同步

你可能会问:既然全量计算简单又一致,为什么还要用增量?

我举个例子。之前有个电商客户,订单表每天增长3000万条。全量跑一次T+1报表要40分钟,业务方说「我要看实时GMV,延迟不能超过1分钟」。40分钟 vs 1分钟,全量计算直接出局。

但增量计算也有坑。我曾经在一个项目中,因为没处理好乱序数据,导致实时大屏上的销售额跳来跳去——一会儿涨100万,一会儿又跌回去。业务方差点以为系统被黑了。所以,选增量计算之前,先问问自己:你的场景能接受多少数据不一致?

我的建议:不要非此即彼。很多成熟系统是「增量为主 + 全量兜底」的混合模式。比如每5分钟做一次增量计算,每天凌晨做一次全量校准。这样既有实时性,又有最终一致性。

增量计算的应用场景

增量计算不是银弹,但它在三个场景里几乎是标配。我按自己的经验排个序:

1. 实时数仓

这是增量计算最典型的战场。实时数仓的核心诉求就是「数据从产生到可查询,延迟越低越好」。

我记得有个金融项目,需要实时计算用户的持仓市值。全量计算要扫描几亿条持仓记录,耗时太长。我们改用增量计算:只处理当天发生交易的账户,其他账户沿用昨天的计算结果。最终延迟从30分钟降到了5秒以内。

实时数仓里常见的增量计算模式:

  • 实时ETL——只处理新增/变更的数据行
  • 实时聚合——维护一个中间状态,新数据到来时增量更新
  • 实时关联——用窗口缓存部分数据,避免全表扫描

2. 流处理

流处理本身就是增量计算的「亲儿子」。每条数据到来时,计算引擎只处理这一条,然后更新结果。

举个例子,Flink的窗口聚合:

// 全量思维:每天跑一次SQL,统计所有订单
SELECT date, SUM(amount) FROM orders GROUP BY date;

// 增量思维:每来一条订单,更新一次SUM
DataStream<Order> orders = ...;
orders
  .keyBy(order -> order.getDate())
  .window(TumblingProcessingTimeWindows.of(Time.days(1)))
  .reduce((o1, o2) -> new Order(o1.getDate(), o1.getAmount() + o2.getAmount()));

看到区别了吗?全量是「算完所有数据再出结果」,增量是「来一条算一条」。后者天然适合流处理。

但这里有个容易踩的坑:状态管理。流处理引擎需要维护中间状态(比如窗口里的累加值),如果状态太大或者状态后端配置不当,很容易OOM。我曾经有个线上事故,就是因为状态没做TTL,结果跑了三天后状态膨胀到几百GB,直接把TaskManager撑爆了。

避坑指南:流处理中的增量计算,一定要给状态设置合理的TTL(Time-To-Live)。Flink中可以用 StateTtlConfig 控制,别等到线上出问题才想起来。

3. CDC(Change Data Capture)

CDC是增量计算的「数据源担当」。没有CDC,增量计算就是无米之炊。

CDC的核心能力是捕获数据库的变更事件(INSERT/UPDATE/DELETE),然后推送给下游。常见的CDC工具:

  • Debezium——基于MySQL binlog、PostgreSQL WAL等
  • Canal——阿里开源的MySQL binlog解析工具
  • Maxwell——也是MySQL binlog,但输出格式更灵活

我个人的经验是:CDC + 消息队列 + 流计算引擎,是构建实时数据管道的最佳组合。比如:

MySQL binlog → Debezium → Kafka → Flink → 实时数仓

这套链路里,Debezium负责捕获增量变化,Kafka负责缓冲和分发,Flink负责增量计算。每一层各司其职。

但CDC也有坑。我记得有一次,MySQL主库做了DDL操作(加了一列),结果Debezium的schema缓存没更新,下游Flink任务直接报错。从那以后,我养成了一个习惯:CDC链路一定要做schema兼容性测试,而且要有自动化的schema演进机制。

知识体系总览

下面这张图,把本章的核心脉络串起来了。你可以把它当作增量计算的「地图」,后续章节都会围绕这些节点展开。

增量计算知识体系总览 增量计算知识体系总览 增量计算 变化捕获 变化传递 状态合并 全量计算:全部数据重算 增量计算:只算变化部分 实时数仓 流处理 CDC 实时ETL / 实时聚合 窗口计算 / 状态管理 Debezium / Canal / Maxwell 增量为主 + 全量兜底 = 最佳实践

这张图从左到右展示了增量计算的完整脉络:从「三个要素」到「全量 vs 增量对比」,再到「三大应用场景」。你可以看到,变化捕获、变化传递、状态合并是底层能力,实时数仓、流处理、CDC是上层应用。后续章节会逐一深入每个节点。

好了,第一章就到这里。增量计算不是什么高深的技术,但它确实能解决很多实际问题。记住一句话:能算增量,就别全量重算——除非你不在乎时间和资源。