开放问答
同一指标实时流与 T+1 离线两条链路算出两个数,怎么对齐口径又不牺牲实时性?
该问题的正文、回答与评论。
提问者 许寒山 · 状态 open
指标口径实时计算FlinkT+1离线数据对账
【背景】 我做了 10 年技术文档,近两年转做指标体系搭建,负责一条 B 端 SaaS 的核心大盘。其中「今日活跃会话数」这个指标,公司要求白天看实时大盘、月底看月报,于是我们跑了两条链路:
- 实时:Flink 消费 Kafka 事件流,按 event_ts 做 5 分钟窗口聚合,落 ClickHouse,BI 直接查;
- 离线:每日 T+1 用 Airflow 调度 Spark,从同一份 ODS 事件表按自然日重算,落数仓 ADS 层。
理论上两者应同口径,但实际对不上。
【现象(具体)】 以昨天为例:实时大盘收口时显示「今日活跃会话数 = 18,432」,而 T+1 月报里「昨日活跃会话数 = 17,905」,差了约 2.9%。差异不是偶发,几乎每天都有 1%–4% 的偏差,且方向固定——实时总是偏高。拆到小时看,偏差集中在 23:50–24:00 这一小时,其余时段基本吻合。
【已尝试的排查与结果】
- 怀疑双流源不同:核对后两条链路消费的是同一份 Kafka topic / 同一张 ODS 表,source 一致,排除。
- 怀疑时间字段:实时用事件自带的 event_ts,离线用 ingest_ts(落库时间)。我一度以为是这个,但把离线也改成 event_ts 后,差异只缩小到 0.8%,主因不是时间字段。
- 怀疑窗口边界:Flink 5 分钟窗口用的是 Tumble 闭区间,离线按自然日 [00:00, 24:00)。23:50–24:00 的偏差我怀疑和「事件 event_ts 落在 24:00 前、但 Flink 处理时已跨到次日窗口」有关,但没验证透。
- 怀疑去重逻辑:实时是「按 session_id 在窗口内去重」,离线是「按 session_id 在全天去重」——一个跨窗口的长会话在实时里可能被算两次、在离线里只算一次,这能解释「实时偏高」,但我不确定是不是全部差异的来源。
【期望得到的答案形态】 我不想只听到「建单一事实源 / 写指标字典」这种正确但落不了地的话。希望能具体到:
- 实时与离线必须在哪些点上强制同口径(时间字段、去重粒度、窗口/分区边界、迟到数据 watermark 处理),哪些点允许合理偏差;
- 针对「跨窗口长会话被重复计数」这类问题,业界常见的工程解法(比如用 session 级状态而非窗口去重、或离线做权威 + 实时只做近似);
- 有没有一个可复现的「对账 SQL / 对账任务」模板,能在每天 T+1 后自动算出两链路的逐小时 diff 并告警,把 2.9% 这种偏差定位到具体小时和具体 session;
- 以及一个判断标准:偏差在什么量级内可以接受、必须治理。
评论
暂无评论。