Skip to content

第十一章:流处理

1. 流处理的核心范式

流处理(Stream Processing)面向无界事件序列,强调“持续计算 + 低延迟反馈”。它不是批处理的对立面,而是把“全量重算”改为“增量更新”。

2. 事件流传输模型

2.1 直接消息传输

生产者直接调用消费者(TCP/HTTP/RPC)实现简单,但耦合高、容错弱,消费者不可用时易丢消息。

2.2 消息代理

引入 Broker 解耦生产与消费,实现缓冲、重试和多订阅。

2.2.1 传统队列模型

RabbitMQ/ActiveMQ 常见“消费即删除”,适合任务分发,但历史回放能力弱。

2.2.2 日志模型

Kafka/Pulsar/Kinesis 采用分区追加日志,消费者以 offset 自主推进,支持回放与多消费组并行。

2.3 分区日志关键语义

  • 单分区内有序。
  • 跨分区无全局顺序。
  • 保留策略按时间或大小控制。

3. 数据库与流的统一视角

3.1 双写问题

应用同时写数据库与搜索/缓存会产生竞态与不一致。更稳妥模式是“单一事实来源 + 变更流派生”。

3.2 变更数据捕获(CDC)

从数据库 WAL/Binlog 提取变更事件,驱动下游索引、数仓和缓存同步,降低跨系统耦合。

3.3 事件溯源(Event Sourcing)

把状态变化建模为不可变事件序列,当前状态由事件回放得到。它比“直接改状态”更有审计性与可追溯性。

3.4 日志压缩

按键保留最新值可控制日志体积,并支持快速重建当前快照状态。

4. 流处理模式

4.1 CEP 与流分析

  • CEP:检测复杂事件模式。
  • 流分析:实时聚合指标,如 UV、分位数、异常检测。

4.2 物化视图维护

流作业可持续维护查询友好的下游视图,本质是“增量更新数据库”。

4.3 流上的搜索与告警

通过规则引擎和索引维护,可实现近实时检索与异常告警。

5. 时间语义

5.1 事件时间与处理时间

  • 事件时间:事件真实发生时刻。
  • 处理时间:系统实际处理时刻。

两者受网络与排队影响可能严重偏离,统计口径应优先基于事件时间。

5.2 窗口机制

常见窗口包括滚动窗口、滑动窗口、跳跃窗口和会话窗口,选择取决于业务语义与延迟目标。

5.3 迟到数据与水位线

水位线用于表达“某时刻之前的数据大概率已到齐”。迟到事件可选择丢弃、修正或补偿,需在准确性与时效性间权衡。

6. 流 Join

6.1 流-流 Join

必须限定时间窗口并维护状态,避免无限缓存导致状态爆炸。

6.2 流-表 Join

常用于事件富化。为了低延迟,维表通常通过 CDC 同步到本地状态而非远程实时查询。

6.3 表-表 Join

通过持续消费两侧变更流维护物化连接结果,适合实时画像与时间线场景。

7. 容错与 Exactly-once

7.1 微批与检查点

  • 微批:把流切成小批次复用批处理容错。
  • 检查点:定期持久化算子状态,故障后从最近快照恢复。

7.2 Exactly-once 的边界

工程上的 Exactly-once 更准确地说是 Effectively-once,通常依赖:

  • 可重放输入。
  • 状态更新与位点提交原子化。
  • 下游写入幂等或事务化。

7.3 端到端一致性

只要链路中某一环节不支持幂等或事务,端到端 Exactly-once 就会退化为“至少一次 + 去重补偿”。

8. 实务建议

  • 先定义时间语义,再设计窗口与迟到策略。
  • 把状态大小、重放成本、恢复时间纳入容量规划。
  • 用批处理定期回放校准流处理结果,构建闭环数据质量体系。