乐趣区

关于flink:踩坑记-Flink-事件时间语义下数据乱序丢数踩坑

本文具体介绍了在上游应用解决工夫语义的 flink 工作呈现故障后,重启生产大量积压在上游的数据并产出至上游数据乱序特地重大时,上游 flink 工作应用事件工夫语义时遇到的大量丢数问题以及相干的解决方案。

本文分为以下几个局部:

  • 「1. 本次踩坑的利用场景」
  • 「2. 利用场景中产生的丢数故障剖析」
  • 「3. 待修复的故障点」
  • 「4. 丢数故障解决方案及原理」
  • 「5. 总结」

利用场景

利用场景如下:

  • 「flink 工作 A」「解决工夫」 语义做过滤产出新增 xx 明细数据至 「Kafka Y」
  • 「flink 工作 B」「事件工夫」 语义生产 「Kafka Y」 做窗口聚合操作产出分钟级别聚合指标至 「Kafka Z」
  • 「Kafka Z」 实时导入至 「Druid」 以做即时 OLAP 剖析,并且展现在 BI 利用看板

丢数故障剖析

简要介绍下这次生产中故障场景。整条故障追踪链路如下:

故障一:

  • 收到报警反馈 「flink 工作 A」 入口流量为 0
  • 定位 「flink 工作 A」 中某个算子的故障导致整个 job 卡住
  • 导致此 「flink 工作 A」 上游 「kafka X」 积压了大量数据
  • 重启 「flink 工作 A」后,生产大量积压在上游 「kafka X」 数据实现,工作恢复正常

故障一从而引发上游的故障二:

  • 因为 「flink 工作 A」 应用了 「解决工夫」 语义解决数据,并且有过滤和 keyBy 分桶窗口逻辑,在重启后生产大量积压在上游的数据时,导致 sink rebalance 后产出到上游 「kafka Y」 各个分区数据中的 server_timestamp 是乱序的
  • 上游 「flink 工作 B」 在生产 「Kafka Y」 时应用了 「事件工夫」 语义解决数据,并且应用了数据中的 server_timestamp 作为 「事件工夫」 工夫戳
  • 「flink 工作 B」 生产了乱序很重大的数据之后,导致在窗口聚合计算时失落了大量数据
  • 最终展现在 BI 利用中的报表有失落数据的状况

待修复的故障点

  • 1.「flink 工作 A」 的稳定性故障,这部分解决方案暂不在本文中介绍
  • 2.「flink 工作 B」 生产上游乱序丢数故障,解决方案在下文介绍

解决方案以及原理

丢数故障解决方案

解决方案是以上游 「flink 工作 B」 作为切入点,间接给出 「flink 工作 B」 的 sql 代码解决方案,java code 也能够依照这个计划实现,其本质原理雷同。下文进行原理解释。

SELECT
  to_unix_timestamp(server_timestamp / bucket) AS timestamp, -- format 成原有的事件工夫戳
  count(id) as id_cnt,
  sum(duration) as duration_sum
FROM
  source_table
GROUP BY
  TUMBLE(proctime, INTERVAL '1' MINUTE),
  server_timestamp / bucket -- 依据事件工夫分桶计算,将雷同范畴(比方 1 分钟)事件工夫的数据分到一个桶内

解决方案原理

首先明确一个无奈防止的问题,在不思考 watermark 容许提早设置特地大的状况下,只有上游应用到了解决工夫语义,上游应用事件工夫语义,一旦上游产生故障重启并在短时间内生产大量数据,就不可避免的会呈现上述谬误以及故障。

在上游生产方依然须要将对应事件工夫戳的数据展现在 BI 平台报表中、并且全链路工夫语义都为解决工夫保障不丢数的前提下。解决方案就是在聚合并最终产出对应事件工夫戳的数据。

最初的计划如下:整条链路全副为解决工夫语义,窗口计算也应用解决工夫,然而产出数据中的工夫戳全副为事件工夫戳。在呈现故障的场景下,一分钟的窗口内的数据的事件工夫戳可能相差几个小时,但在最终窗口聚合时能够依据事件工夫戳划分到对应的事件工夫窗口内,上游 BI 利用展现时应用此事件工夫戳即可。

留神:sql 中的 bucket 须要依据具体应用场景进行设置,如果设置过于小,比方非故障场景下依照解决工夫开 1 分钟的窗口,bucket 设为 60000(1 分钟),那么极有可能,这个工夫窗口中所有数据的 server_timestamp 都集中在某两分钟内,那么这些数据就会被分到两个桶(bucket)内,则会导致重大的数据歪斜。

输出数据样例

模仿上述故障,「flink B」 的工作某一个窗口内的数据输出如下。

server_timestamp id duration
2020/9/01 21:14:38 1 300
2020/9/01 21:14:50 1 500
2020/9/01 21:25:38 2 600
2020/9/01 21:25:38 3 900
2020/9/01 21:25:38 2 800

输入数据样例

依照上述解决方案中的 sql 解决过后,输入数据如下,则能够解决此类型丢数故障。

timestamp id_cnt duration_sum
2020/9/01 21:14:00 2 900
2020/9/01 21:25:00 3 2300

总结

本文剖析了在 flink 利用中:

  • 「上游应用解决工夫语义的 flink 工作呈现故障、重启生产大量积压数据并产出至上游数据乱序特地重大时,上游应用事件工夫语义时遇到的大量丢数问题」
  • 「以整条链路为解决工夫语义的前提下,产出的数据工夫戳为事件工夫戳解决上述问题」
  • 「以 sql 代码给出了丢数故障解决方案样例」

学习材料

flink

  • https://github.com/flink-chin…
  • https://ververica.cn/develope…
  • https://space.bilibili.com/33…

退出移动版