首页/数据/数据工程与 ETL 速查/事件时间与处理时间 Event/Processing Time
管道基础52 条

事件时间与处理时间 Event/Processing Time

事件时间是数据实际发生的时间(常来自记录里的时间戳),处理时间是引擎处理到它的时刻。两者存在乱序与延迟差,流处理以事件时间语义保证结果可复现。

三个时间概念

事件时间(Event Time)是数据实际发生的时刻,通常取自记录里的时间戳字段;处理时间(Processing Time)是引擎处理到这条记录时的本地时钟;摄入时间(Ingestion Time)是数据进入引擎系统的时刻,介于两者之间。三者中只有事件时间与数据的业务含义绑定,处理时间只反映机器的忙碌程度。

为什么对外指标要用事件时间

用处理时间统计时,网络延迟、积压或重启都会改变结果:同一批数据重跑两次,得到的数字可能完全不同。事件时间把归属交给数据本身,窗口边界与业务日期一致,结果可复现、可核对,也能与批处理口径对齐。

三种时间对照

时间语义来源特点
事件时间记录内的时间戳字段可复现、与业务对齐,需要水位线配合
处理时间引擎所在机器的本地时钟实现最简单,但不可复现,受积压影响
摄入时间记录进入引擎的时刻介于两者之间,不依赖数据自带时间戳

基本信息

事件时间数据自带的发生时间,从记录字段中提取
处理时间引擎本地时钟,结果随运行环境变化
配套机制事件时间需要水位线判断完整性
对齐要求多源时间戳的时区与格式必须先统一
典型取舍延迟敏感用处理时间,口径敏感用事件时间

典型使用场景

  • 对外报表与看板:按事件时间统计,多个来源口径才能对齐
  • 跨系统对账:事件时间让两侧按同一业务时刻切分数据
  • 实时告警:可以先用处理时间快速出结果,同时用事件时间做准
  • 补数与重跑:重放历史数据时事件时间保证结果与首次一致
  • 延迟分析:比较事件时间与处理时间之差,量化链路延迟

Flink SQL 声明事件时间

Flink SQL 声明事件时间
-- 把业务时间字段声明为事件时间,并给出允许迟到的时间
CREATE TABLE orders (
  order_id  STRING,
  amount    DECIMAL(10,2),
  ts        TIMESTAMP(3),                        -- 事件时间字段
  WATERMARK FOR ts AS ts - INTERVAL '5' SECOND  -- 容忍 5 秒乱序
) WITH ('connector' = 'kafka', 'topic' = 'orders', 'format' = 'json');

-- 窗口按事件时间切分:结果与数据发生时刻绑定,重启重跑可复现
SELECT TUMBLE_START(ts, INTERVAL '1' MINUTE) AS w, SUM(amount)
FROM orders GROUP BY TUMBLE(ts, INTERVAL '1' MINUTE);
排查两套数字对不上时,先确认双方用的是哪种时间语义。实时链路按处理时间出数、离线链路按事件时间出数,是口径差异的常见来源,而不是数据本身错了。
用处理时间做统计并对外发布,重跑同一批数据会得到不同结果;对账时无法解释差异,也无法验证哪一次是对的。

易错点

  • 源系统时间戳不统一(本地时间与 UTC 混用),窗口整体错位,数据集中在相邻两个窗口里
  • 把时间字段建成字符串再在查询中转换,格式异常的行直接报错或丢数,入库前应先做格式校验
  • 用处理时间做对外口径,重跑结果不一致,对账时无法定位到底哪次正确
  • 以为声明了事件时间就万事大吉:没有水位线配合,窗口不会触发,数据只进不出

数据来源与参考

  • Apache Flink 官方文档:Timely Stream Processing
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌