背景
网易新闻是中国领先的全媒体新闻门户网站,提供全面、及时、权威的新闻资讯服务。推荐产品团队主要致力于网易新闻 APP 端内资讯的个性化推荐,加强用户粘性,提高用户的阅读体验。
随着业务的持续发展,原有的推荐数仓架构逐渐满足不了业务对数据的多样性需求,数据处理流程也愈发复杂。近期,我们与杭研同事一起深入调研了数据湖方案 Apache Paimon,以此为底座,旨在解决传统数仓在数据更新能力上存在的痛点。
基于 Partial-Update 构建实时大宽表
网易新闻从推荐业务内容看,主要包括头条、视频、跟帖、圈子等,推荐数仓会对每个内容构建主题宽表,宽表的应用广泛,查询率高,保证宽表数据的高效、稳定产出对推荐数仓业务线具有重要影响。在传媒新闻推荐场景中,包含两种业务形态:
- 推荐去重场景:即对于任意用户不会重复推荐相同文章;
- 推荐不去重场景:如付费业务,为了提高付费转化率,推荐引擎会对历史推荐过单没有曝光的优质文章进行多次推荐;
推荐去重
该场景容易定义唯一key(devid+docid),其中 devid 表示用户设备的唯一 id,docid 表示文章 id。由于不存在重复推荐的情况,通过该组合即可唯一定义一条用户推荐数据。以头条宽表为例,原有的数据处理流程如下: 原宽表数据计算链路
其中,datastream 是网易内部的数据同步工具, 可实现 Kafka 到 HDFS 的数据落盘。
离线join计算
头条宽表的计算逻辑:以 devid+docid 为 primary key,用 sdk 数据匹配推荐数据,sdk 中我们关注的最主要指标为曝光(exp)、点击(clk)、阅读时长(du),简化数据结构如下:
devid | docid | rec_reason | rec_time | exp | clk | du |
111 | aaa | A | 2023-11-20 10:00:00 | false | false | 0 |
222 | bbb | B | 2023-11-20 10:10:00 | true | false | 0 |
333 | ccc | C | 2023-11-20 10:20:00 | true | true | 20 |
该实现方案较为简单粗暴,先使推荐数据流 rec 和用户行为数据流 sdk 落盘 HDFS,再基于 Spark 离线计算前一小时的 rec left join 前一小时 sdk( sdk 数据范围多一段 gap 时间,降低数据漂移的影响)。此方案存在的问题:数据可见时间为 H+1,实时性不佳;数据质量一般。
针对以上问题,我们基于 Flink + Paimon 重构优化了头条宽表的计算逻辑,数据近实时落盘,并实现了部分表字段的 partial-update 能力,从而实现准实时宽表的构建。新方案解决大宽表数据可见性长的问题,头条宽表由原来的 H+1 时间延迟提升至分钟级延迟;同时也优化了宽表计算的数据处理链路,节省存储计算资源。
基于 Paimon 的实时宽表计算流程图Apache Paimon 支持启动多个实时任务写入同一张 Paimon 表,但在实际开发过程中,我们选择同一个任务多流 Union 方式写入,该方式可以直接使用写入任务做 Compaction ,使用起来相对简单。对于按照时间分区的表来说,分区边界附近仍存在一定程度的数据漂移,主要是 sdk 数据。例如2023-11-27 23:10:00 的 rec 和 2023-11-28 00:00:01 的 sdk 数据匹配不上,我们采用冗余分区边界附近的 sdk 数据的方式处理,分别向两个分区发送 sdk 数据。
推荐不去重
由于文章存在重复推荐的问题,不能简单的用 devid+docid 方式来确认 primary key,重新设计主键为 devid+docid+rec_time,其中 rec_time 表示文章对应的推荐时间戳。
由于 rec 数据和 sdk 数据上游产出业务方不同,且数据不完全互通,sdk 数据拿不到 rec 数据的 rec_time 字段。根据业务推荐特点,由于重复推荐只有在没有曝光的情况下才会发生,sdk 数据只需要匹配最新的对应 rec 数据即可。缓存一段时间的 rec 数据,基于 Flink 的 map-state 保留 devid+docid 对应的最新 rec_time ,即 sdk 数据从缓存中获取对应的 rec_time 作为自身的 rec_time,从而构建完整的 key。不过这种方案目前如果 rec 数据消费压力过大会存在数据准确性问题, 由于业务方对准确性要求不高,所以偶尔发生这种情况也能容忍。
重复推荐 Paimon 宽表数据处理流程图实际数据结果简化之后如下:
devid | docid | rec_reason | rec_time | exp | clk | du |
111 | aaa | A | 2023-11-20 10:00:00 | false | false | 0 |
222 | bbb | B | 2023-11-20 10:00:00 | false | false | 0 |
111 | aaa | A | 2023-11-20 10:30:00 | true | true | 20 |
222 | bbb | B | 2023-11-20 10:30:00 | false | false | 0 |
总体而言,引入 Apache Paimon 后,在宽表计算方面有效解决了老架构存在的痛点问题:
- 数据实时性得到有效提升,从原来小时级可见提升至分钟级(取决于 Flink checkpoint 时间),这对于实时性要求较高的业务具有重要作用,如策略在调整线上参数后效果随时可见,不再需要 H+1 时间等待;
- 数据处理链路在一定程度上也得到了优化,降低成本开销。
优化数据统计链路实现降本
以推荐数字化业务需求为例,介绍传媒基于 Paimon 在数据链路处理上的降本增效落地实践。推荐数字化,顾名思义就是将推荐过程中的多项指标以数字化的形式展现出来,用于计算每篇文章在推荐理由、推荐阶段(召回、排序等)、AB 实验维度的推荐次数。该数据无论是开发同学在排查问题还是策略同学在数据分析方面都有着广泛应用,有助于优化推荐准确性、提升转化率、优化资源配置等。
推荐数字化业务的原始数据,简化数据结构如下:
docid | rec_reason | step_name | ab_id | num |
aaa | NCF | recall | 111 | 2 |
bbb | STEP_LOG | after-filter | 222 | 8 |
ccc | ND_PFIDEMB | art_feat | 333 | 5 |
原数据处理流程图如下:
原推荐数字化处理链路图推荐数字化处理链路较长,且数据处理量大,平均 qps 20000+,导致相关任务处理的资源开销大。另外,在推荐数字化处理过程中,需要对引擎生成的原始数据进行聚合 (sum) 操作,聚合计算不同维度下的推荐值,最终生成小时级别的 DWS 表提供给下游用户使用。而 paimon 的 aggregation 引擎天然支持这一该场景,能够轻松应对。基于以上分析,引入 Apache Paimon 后,优化后的数据处理链路图如下:
基于 Paimon 的推荐数字化数据处理链路图
优化之后,该业务在数据处理阶段取得了显著的效果:
- 提升数据可见性:数据处理模式由原来的定时批处理模式(小时级)优化为实时写入,对于部分实时性要求高的场景非常重要,提供更好的用户体验。
- 降低资源消耗:通过缩短链路,可以减少资源的使用量,提高系统的效率,降低成本。
- 简化系统架构:较短的数据处理链路可以简化数据流程和逻辑,使系统更加灵活、可维护和易于扩展。
未来计划
- 传媒场景中的很多实时大宽表业务中的 Partial-Update 表只有少量数据会关联上,很多非关联上的数据是不需要的,后面会引入数据淘汰策略,淘汰掉这些数据。
- 用 Paimon 跨分区更新能力解决分区交界出数据漂移问题。