2. 流式处理基础:流式计算概念、与批处理的区别、Apache Kafka / Flink / Spark Streaming 简介
2.1 流式计算的核心概念
在组合风险归因场景中,市场数据、交易指令、保证金变动以毫秒级持续产生。传统批处理无法满足实时风控的时效性要求,因此需要引入流式计算。
流式计算是一种无界数据处理范式:数据持续到达,系统在数据产生后立即或极低延迟内完成计算,并持续输出结果。核心特征包括:
- 无界数据集:数据流理论上永不终止,无法预知总数据量。
- 事件驱动:每条数据(事件)到达即触发计算逻辑。
- 低延迟:从数据产生到结果输出通常在秒级甚至毫秒级。
- 状态管理:流计算算子需要维护中间状态(如滚动 VaR 计算中的历史窗口)。
- 时间语义:支持事件时间(Event Time)、处理时间(Processing Time)和摄入时间(Ingestion Time)。
风险归因场景提示: 组合风险归因中的“边际风险贡献”和“成分 VaR”需要基于最新持仓和因子暴露实时重算,流式计算天然适合这种持续更新的计算模型。
2.2 流式计算与批处理的区别
批处理(Batch Processing)处理有界数据集,数据先存储后计算,延迟通常在分钟到小时级。下表从多个维度对比两种模式:
| 对比维度 | 批处理 | 流式计算 |
|---|---|---|
| 数据特征 | 有界、已知大小 | 无界、持续到达 |
| 触发方式 | 定时调度或手动触发 | 事件到达即触发 |
| 延迟 | 分钟~小时级 | 毫秒~秒级 |
| 计算模型 | 全量数据扫描 | 增量逐条或微批次 |
| 状态持久化 | 中间结果写磁盘/DB | 内存状态 + 定期 checkpoint |
| 典型场景 | 日终报表、历史回测 | 实时风控、盘中对冲 |
常见误区: 流式计算并非完全替代批处理。在组合风险归因中,日终的全面风险报告仍可使用批处理,而盘中实时监控则依赖流式计算。两者常以 Lambda 架构或 Kappa 架构共存。
2.3 流式处理架构总览
一个典型的流式处理管道包含三个核心层:消息队列层(数据缓冲与分发)、计算引擎层(流式 SQL 执行)、结果输出层(实时仪表盘/告警)。下图展示了组合风险归因场景下的流式架构:
2.4 三大核心组件简介
2.4.1 Apache Kafka — 分布式消息队列
Kafka 是流式架构的数据中枢,负责高吞吐、持久化地收集和分发实时数据流。核心概念:
- Topic:数据流的逻辑分类,如
market_tick、trade_order。 - Partition:Topic 的物理分片,实现并行读写和水平扩展。
- Consumer Group:一组消费者协同消费同一 Topic,每个 Partition 只被组内一个消费者处理。
- Offset:消息在 Partition 内的唯一序号,支持回溯消费。
风险归因应用: 将市场行情、交易指令、因子暴露数据分别写入不同 Topic,Flink 通过 SQL 连接多个流进行 JOIN 和聚合计算。
2.4.2 Apache Flink — 流式计算引擎
Flink 是本章课程的核心计算引擎,支持真正的逐条流处理和事件时间语义。关键特性:
| 特性 | 说明 | 风险归因场景价值 |
|---|---|---|
| Exactly-Once 语义 | 分布式快照 + 两阶段提交 | 保证 VaR 计算不重复不丢失 |
| 事件时间处理 | 基于数据自带时间戳计算 | 处理乱序到达的行情数据 |
| 状态后端 | RocksDB / Heap 状态存储 | 维护滚动窗口内的持仓和协方差矩阵 |
| Table API & SQL | 声明式流 SQL 接口 | 用 SQL 表达风险归因逻辑,降低开发门槛 |
2.4.3 Spark Streaming — 微批次流处理
Spark Streaming 将流数据切分为微批次(Micro-Batch),每个批次作为 RDD 处理。与 Flink 的对比:
| 对比维度 | Flink | Spark Streaming |
|---|---|---|
| 处理模型 | 逐条事件驱动 | 微批次(Mini-Batch) |
| 延迟 | 毫秒级 | 秒级(批次间隔决定) |
| 时间语义 | 原生事件时间 | 需额外 watermark 机制 |
| 状态管理 | 算子级状态 + 分布式快照 | 基于 DStream 的 updateStateByKey |
| SQL 支持 | 流 SQL 标准支持 | Structured Streaming SQL |
选型建议: 本教程选用 Flink 作为主要引擎,因为其事件时间语义和真正的流处理模型更适合组合风险归因中复杂的窗口计算和乱序数据处理。Spark Streaming 适合延迟容忍度稍高、但需要与 Spark 批处理生态紧密集成的场景。
2.5 流式 SQL 在风险归因中的位置
流式 SQL 将上述组件串联起来:
- Kafka Source:Flink SQL 通过
CREATE TABLE ... WITH ('connector'='kafka')定义输入流。 - 流式查询:使用标准 SQL 进行
SELECT、JOIN、GROUP BY、WINDOW操作。 - 状态化聚合:计算滚动 VaR、边际风险贡献等需要维护窗口状态。
- Kafka Sink:结果写回 Kafka Topic 或直接输出到数据库/仪表盘。
一个简化的流式 SQL 示例(计算组合 VaR):
-- 定义行情输入流
CREATE TABLE market_ticks (
symbol STRING,
price DOUBLE,
ts TIMESTAMP(3),
WATERMARK FOR ts AS ts - INTERVAL '5' SECOND
) WITH (
'connector' = 'kafka',
'topic' = 'market_tick',
'properties.bootstrap.servers' = 'localhost:9092',
'format' = 'json'
);
-- 定义持仓表(来自 Kafka 或维表)
CREATE TABLE positions (
symbol STRING,
quantity DOUBLE,
PRIMARY KEY (symbol) NOT ENFORCED
) WITH (
'connector' = 'jdbc',
'url' = 'jdbc:mysql://localhost:3306/risk',
'table-name' = 'current_positions'
);
-- 流式 JOIN 计算组合市值
SELECT p.symbol, p.quantity * m.price AS market_value
FROM positions p
JOIN market_ticks m
ON p.symbol = m.symbol;