2. 核心概念解析:变更数据捕获(CDC)原理、事件驱动架构基础、流处理与批处理的区别

好,咱们进入第二章。这一章我打算把三个最基础、也最容易混淆的概念掰开揉碎了讲清楚。你想想看,增量计算的核心就是“感知变化”和“快速响应”。那怎么感知变化?靠CDC。怎么组织变化后的动作?靠事件驱动。怎么处理这些源源不断的变化?靠流处理。这三者环环相扣,缺一不可。

我在很多项目里都见过这样的场景:团队把CDC、事件驱动和流处理混为一谈,结果架构设计出来四不像。咱们今天就把它们彻底理清。

2.1 变更数据捕获(CDC)原理

CDC,全称 Change Data Capture,翻译过来就是“变更数据捕获”。说白了,就是监控数据库里的数据变化,然后把每一次的插入、更新、删除操作都抓出来,告诉下游系统。

我习惯把CDC比作一个“数据库的监控摄像头”。它不关心你业务逻辑怎么写的,它只盯着数据文件或者日志文件看,一旦有变化,立刻记录下来。

2.1.1 常见的CDC实现方式

实现CDC的方式有好几种,我挑最主流的三种给你讲讲。

实现方式 原理 典型工具 我踩过的坑
基于日志的CDC 直接读取数据库的事务日志(如MySQL的binlog、PostgreSQL的WAL) Debezium、Canal、Maxwell 日志格式变更导致解析失败,一定要锁定日志版本
基于触发器的CDC 在表上创建触发器,每次DML操作时写入变更记录表 自定义实现 对源库性能影响极大,生产环境慎用
基于时间戳的CDC 在表中增加最后修改时间字段,定期轮询 自定义实现 无法捕获删除操作,且存在时间窗口误差

核心结论:生产环境中,基于日志的CDC是唯一推荐的方式。它性能损耗最小,数据一致性最高,能捕获所有变更类型(包括删除)。

2.1.2 基于日志的CDC工作流程

我拿MySQL的binlog举个例子。Debezium这个工具我用了好几年,它把整个过程封装得很好。

  1. 连接源库:Debezium作为MySQL的slave节点,模拟主从复制协议,请求binlog流。
  2. 读取日志:持续读取binlog文件,解析出每个事务的变更事件。
  3. 生成事件:将解析后的变更封装成标准化的消息结构,包含before(变更前镜像)和after(变更后镜像)。
  4. 发送到消息队列:通常写入Kafka,每个表对应一个Topic。

避坑指南:我曾经遇到过一个案例,binlog文件被误删了,导致CDC断流。后来我强制要求所有项目必须开启binlog的expire_logs_days参数,并且配置Debezium的snapshot.mode为when_needed,这样即使断流也能自动做一次全量快照恢复。

2.2 事件驱动架构基础

有了CDC,我们拿到了数据变更事件。但谁来消费这些事件?怎么组织这些事件的处理逻辑?这就引出了事件驱动架构。

事件驱动架构,说白了就是“发生了什么事,就通知谁”。它和我们传统的“请求-响应”模式完全不同。传统模式是“你调用我,我给你结果”;事件驱动是“我发生了某件事,谁感兴趣谁自己来拿”。

2.2.1 核心组件

  • 事件生产者:产生事件的一方。在我们的场景里,CDC工具就是生产者。
  • 事件通道:传输事件的管道。最常用的是消息队列,比如Kafka、Pulsar。
  • 事件消费者:订阅并处理事件的一方。比如流处理作业、微服务。
  • 事件总线:管理事件的发布和订阅逻辑。

2.2.2 事件驱动 vs 传统API调用

对比维度 事件驱动 传统API调用
耦合度 松耦合,生产者和消费者互不知晓 紧耦合,调用方必须知道被调用方地址
扩展性 消费者可以独立扩缩容 需要协调两端
实时性 异步,近乎实时 同步,受网络延迟影响
数据一致性 最终一致性 强一致性(通常)

注意:事件驱动不是银弹。它引入了异步处理的复杂性,比如事件顺序、重复消费、死信队列等问题。我建议只在需要解耦和实时响应的场景使用,不要为了用而用。

2.3 流处理与批处理的区别

好,现在我们有源源不断的事件流了。怎么处理这些流?这就涉及到流处理和批处理的选择。

我见过很多团队,明明数据是实时流进来的,却非要攒够一批再处理,结果延迟高得离谱。也见过反过来,数据量极小,却非要用流处理框架,搞得运维成本很高。

2.3.1 核心差异

维度 流处理 批处理
数据范围 处理当前到达的一条或一小批数据 处理一个固定数据集(如一天的数据)
延迟 毫秒到秒级 分钟到小时级
触发方式 数据到达即触发 定时触发或手动触发
状态管理 需要维护中间状态(如窗口聚合) 无状态或简单状态
典型框架 Flink、Kafka Streams、Spark Streaming MapReduce、Spark SQL、Hive

2.3.2 什么时候用流处理?

我个人习惯遵循一个原则:如果数据从产生到被消费的延迟容忍度低于1分钟,就用流处理。

举个例子,主数据实时同步。客户在CRM里改了地址,我希望在5秒内同步到ERP、WMS、电商平台。这种场景,批处理根本做不到。

2.3.3 什么时候用批处理?

批处理也有它的优势。比如做月度报表、历史数据归档、全量数据重算。这些场景不需要实时性,批处理的吞吐量更高,成本更低。

我的经验:很多项目其实是“流批一体”的。比如用Flink做实时流处理,同时把结果写到一个离线表里,供批处理任务做T+1的报表。你想想看,这样既保证了实时性,又满足了离线分析的需求。

2.4 三者关系:一张图说清楚

下面这张图,是我自己总结的CDC、事件驱动和流处理在增量计算中的协作关系。你看完应该就全明白了。

CDC、事件驱动与流处理协作关系图 增量计算核心技术栈协作关系 数据源 MySQL / PostgreSQL / Oracle CDC 捕获层 Debezium / Canal 事件通道 Kafka / Pulsar 流处理层 Flink / Kafka Streams 目标系统 ERP / 缓存 / 搜索引擎 读取binlog 发送事件 订阅消费 写入结果 说明: CDC负责捕获数据变更,事件通道负责解耦传输,流处理负责实时计算。 三者组合,构成了增量计算的主干。

2.5 小结

这一章我们讲了三个核心概念:

  • CDC是“眼睛”,负责看数据变了没。
  • 事件驱动架构是“神经系统”,负责把变化通知出去。
  • 流处理是“大脑”,负责对变化做出实时反应。

嗯,这三个概念你吃透了,后面讲增量计算的具体实现,你就不会觉得吃力了。记住,它们不是孤立的技术,而是一个完整的协作链条。