基于以上问题,使用 Paimon 对此链路进行了重构。在 Paimon 链路中,DWD 层直接创建一张以用户 ID、房间 ID 和日期为主键的 Paimon 主键表,并且设置 'changelog-producer' = 'lookup'。在 DWS 层,创建一张以直播间 ID 为主键的聚合表。在 Flink 任务中,只需进行比较简单的操作,将原布尔类型的状态字段转换为 Int 类型的 0 和 1,并直接写入聚合表中,这样便会得到直播间粒度的聚合指标。最后,将计算好的指标写入外部的 KV 存储中,对外提供查询。
2.4 长周期指标聚合计算场景 - 业务收益
Paimon 方案整体解决了 Flink 方案中的大状态问题,因为其将 Flink 中的状态计算下沉到了 Paimon 存储层,所以 Flink 任务状态几乎可以忽略不计。其次,因为和 Flink 方案一样借助了外部的 KV 存储,所以其查询并发可达到百万级别。
2.5 大流量端到端场景 - 业务背景
接下来考察大流量端到端的场景。内部运营希望查看短视频内容的消费指标,从而及时调整其经营策略。但是,由于原始的短视频指标和数据并未携带游戏相关信息,所以需要接入全量的短视频数据,并关联游戏属性,才能计算游戏场景下的短视频聚合指标。最大的挑战在于,全量短视频数据在峰值的 RPS 可达到 800 万左右,这在进行维度关联时带来了巨大的挑战。
2.6 大流量端到端场景 - 方案演进
接下来审视整体的方案演进。首先,采用 Flink + MQ 的方式实现。为避免重复开发,在 DWD 层直接接入短视频团队的视频分钟指标。在 DWD 层,通过 Lookup Join 的方式直接关联外部 KV 存储,从而获取游戏相关信息。但由于全量的短视频分钟指标在峰值时达到 800 万 RPS 左右,所以在 Flink 中将 lookup.cache.ttl 设置为 50 分钟,并且开启 Keyed State,以使整体的缓存命中率保持在 90% 以上。尽管如此,穿透到外部 KV 存储的流量在峰值时依然可达到 40 万 / 秒。
接下来审视 DWS 层。为避免多次关联游戏维表,DWS 层基于分钟指标再次聚合上升到天粒度。因为分钟指标是不断变化的,其数据类型也是 Changelog,但由于 MQ 不支持 Changelog 类型,所以在这里继续使用 Last_Value 在 Flink 任务中构建 Retract 消息。在短视频的指标任务中,按照视频 ID 和日期进行上卷,最终得到短视频粒度的指标。但此过程会产生大量的 Keyed State,导致状态变得非常大,使任务不稳定。