怎么自己做个免费网站吗,商标设计网站推荐,智趣游戏型网站开发,网站如何做前后端分离简介#xff1a; 5 月 22 日北京站 Flink Meetup 分享的议题。 本文整理自爱奇艺技术经理韩红根在 5 月 22 日北京站 Flink Meetup 分享的议题《Flink 在爱奇艺广告业务的实践》#xff0c;内容包括#xff1a; 业务场景业务实践Flink 使用过程中的问题及解决未来规划一、业…简介 5 月 22 日北京站 Flink Meetup 分享的议题。 本文整理自爱奇艺技术经理韩红根在 5 月 22 日北京站 Flink Meetup 分享的议题《Flink 在爱奇艺广告业务的实践》内容包括 业务场景业务实践Flink 使用过程中的问题及解决未来规划一、业务场景 实时数据在广告业务的使用场景主要可以分为四个方面
数据大屏包括曝光、点击、收入等核心指标的展示以及故障率等监控指标异常监测因为广告投放的链路比较⻓所以如果链路上发生任何波动的话都会对整体的投放效果产生影响。除此之外各个团队在上线过程中是否会对整体投放产生影响都是通过异常监测系统能够观测到的。我们还能够观测业务指标走势是否合理比如在库存正常的情况下曝光是否有不同的波动情况这可以用来实 时发现问题;数据分析主要用于数据赋能业务发展。我们可以实时分析广告投放过程中的一些异常问题或者基于当前的投放效果去研究怎样优化从而达到更好的效果;特征工程广告算法团队主要是做一些模型训练用于支持线上投放。技术特征最初大部分是离线随着实时的发展开始把一些工程转到实时。
二、业务实践
业务实践主要分为两类第一个是实时数仓第二个是特征工程。
1. 实时数仓
1.1 实时数仓 - 目标 实时数仓的目标包括数据完整性、服务稳定性和查询能力。
数据完整性在广告业务里实时数据主要是用于指导决策比如广告主需要根据当前投放的实时数据指导后面的出价或调整预算。另外故障率的监控需要数据本身是稳定的。如果数据是波动的指导意义就非常差甚至没有什么指导意义。因此完整性本身是对时效性和完整性之间做了一个权衡服务稳定性生产链包括数据接入、计算多层、数据写入、进度服务和查询服务。除此之外还有数据质量包括数据的准确性以及数据趋势是否符合预期查询能力在广告业务有多种使用场景在不同场景里可能使用了不同的 OLAP 引擎所以查询方式和性能的要求不一致。另外在做数据分析的时候除了最新最稳定的实时数据之外同时也会实时 离线做分析查询此外还包括数据跨源和查询性能等要求。
1.2 实时数仓 - 挑战 数据进度服务需要在时效性和完整性之间做一个权衡。数据稳定性由于生产链路比较长中间可能会用到多种功能组件所以端到端的服务稳定性对整体数据准确性的影响是比较关键的。查询性能主要包括 OLAP 分析能力。在实际场景中数据表包含了离线和实时单表规模达上百列行数也是非常大的。
1.3 广告数据平台架构 上图为广告数据平台基础架构图从下往上看
底部是数据采集层这里与大部分公司基本一致。业务数据库主要包含了广告主的下单数据以及投放的策略埋点日志和计费日志是广告投放链路过程中产生的日志 中间是数据生产的部分数据生产的底层是大数据的基础设施这部分由公司的一个云平台团队提供其中包含 Spark / Flink 计算引擎Babel 统一的管理平台。Talos 是实时数仓服务RAP 和 OLAP 对应不同的实时分析以及 OLAP 存储和查询服务。 数据生产的中间层是广告团队包含的一些服务例如在生产里比较典型的离线计算和实时计算。 离线是比较常见的一个分层模型调度系统是对生产出的离线任务做有效的管理和调度。实时计算这边使用的引擎也比较多我们的实时化是从 2016 年开始当时选的是 Spark Streaming后面随着大数据技术发展以及公司业务需求产生了不同场景又引入了计算引擎 Flink。实时计算底层调度依赖于云计算的 Babel 系统除了计算之外还会伴随数据治理包括进度管理就是指实时计算里一个数据报表当前已经稳定的进度到哪个时间点。离线里其实就对应一个表有哪些分区。血缘管理包括两方面离线包括表级别的血缘以及字段血缘。实时主要还是在任务层面的血缘。至于生命周期管理在离线的一个数仓里它的计算是持续迭代的。但是数据保留时间非常长的话数据量对于底层的存储压力就会比较大。数据生命周期管理主要是根据业务需求和存储成本之间做一个权衡。质量管理主要包括两方面一部分在数据接入层判断数据本身是否合理另外一部分在数据出口就是结果指标这一层。因为我们的数据会供给其他很多团队使用因此在数据出口这一层要保证数据计算没有问题。 再上层是统一查询服务我们会封装很多接口进行查询。 因为数据化包括离线和实时另外还有跨集群所以在智能路由这里会进行一些选集群、选表以及复杂查询、拆分等核心功能。查询服务会对历史查询进行热度的统一管理。这样一方面可以更应进一步服务生命周期管理另一方面可以去看哪些数据对于业务的意义非常大。除了生命周期管理之外它还可以指导我们的调度系统比如哪些报表比较关键在资源紧张的时候就可以优先调度这些任务。再往上是数据应用包括报表系统、Add - hoc 查询、数据可视化、异常监控和下游团队。
1.4 实时数仓 - 生产链路 数据生产链路是从时间粒度来讲的我们最开始是离线数仓链路在最底层的这一行随着实时化需求推进就产生了一个实时链路整理来说是一个典型的 Lambda 架构。
另外我们的一些核心指标比如计费指标因为它的稳定性对下游比较关键所以我们这边采用异路多活。异路多活是源端日志产生之后在计算层和下游存储层做了完全的冗余在后面的查询里做统一处理。
1.5 实时数仓 - 进度服务 上文介绍了我们要求提供出去的实时数据的指标是稳定不变的进度服务实现的核心点包括时间窗口里指标的变化趋势同时结合了实时计算任务本身的状态因为在实时数仓里很多指标是基于时间窗口做聚合计算。
比如一个实时指标我们输出的指标是 3 分钟也就是说 400 这个时间点的指标的就包括了 400403 的数据403 包括了 403406 的数据其实就是指一个时间窗口的数据什么时候是对外可见的。因为在实时计算里数据不断进来 400 的时间窗口的数据从 400 开始指标就已经开始产生了。随着时间叠加指标不断上升最后趋于稳定。我们基于时间窗口指标的变化率来判断它是否趋于稳定。
但如果只是基于这个点来看那么它还存在一定的弊端。
因为这个结果表的计算链会依赖很多个计算任务如果这个链路上面哪个任务出现问题可能会导致当前的指标虽然走势已经趋于正常但是最终并不完整。所以在这基础之上我们又引入了实时计算任务状态在指标趋于稳定的时候同时去看生产链路上这些计算任务是否正常如果是正常的话表示任务本身时间点的指标已经稳定可以对外提供服务。
如果计算有卡顿、堆积或者已经有异常在重启过程中就需要继续等待迭代处理。
1.6 实时数仓 - 查询服务 上图为查询服务架构图。
最下方是数据里面有实时存储引擎包括 Druid 等。在离线中数据在 Hive 里边但是在做查询的时候会把它们进行 OLAP 的同步在这边使用的是两种引擎。为了和 Kudu 做 union 查询会把它同步到 OLAP 引擎然后上面去统一使用 Impala 做查询。另外对于使用场景里比较固定的方式可以导到 Kylin 里然后在上面做数据分析。
基于这些数据会有多个查询节点再上面是一个智能路由层。从最上面查询网关当有一个查询请求进来首先判断它是不是一个复杂场景。比如在一个查询里如果它的时长同时跨越了离线和实时这里就会同时使用到离线表和实时表。
另外离线表里还有更复杂的选表逻辑比如小时级别天级别。经过复杂场景分析之后就会把最终选择的表大概确定下来。其实在做智能路由的时候才会去参考左边的一些基础服务比如元数据管理当前这些表的进度到哪个点了。
对于查询性能的优化在数据里底层扫描的数据量对最终性能的影响是非常大的。所以会有一个报表降维根据历史的查询去做分析。比如在一个降维表包含哪些维度可以覆盖到百分之多少的查询。
1.7 数据生产 - 规划 之前在实时数据报表生产里提到它主要是基于 API 的方式实现的。Lambda 架构本身有一个问题就是实时跟离线是两个计算团队对于同一个需求需要两个团队同时去开发这样会带来几个问题。
一方面是他们的逻辑可能会发生差异最终导致结果表不一致另一方面是人力成本同时需要两个团队进行开发。
因此我们的诉求是流批一体思考在计算层是否可以使用一个逻辑来表示同一个业务需求比如可以同时使用流或者批的计算引擎来达到计算的效果。
在这个链路里边原始数据通过 Kafka 的方式接入进来经过统一的 ETL 逻辑接着把数据放在数据湖里。因为数据湖本身可以同时支持流和批的方式进行读写而且数据湖本身可以实时消费所以它既可以做实时计算也可以做离线计算然后统一把数据再写回数据湖。
前文提到在做查询的时候会使用离线跟实时做统一整合所以在数据湖里写同一个表在存储层面可以省去很多工作另外也可以节省存储空间。
1.8 数据生产 - SQL 化 SQL 化是 Talos 实时数仓平台提供的能力。
从页面上来看它包括了几个功能左边是项目管理右边包括 Source、Transform 和 Sink。
有一些业务团队本身对于计算引擎算子非常熟那么他们便可以做一些代码开发但是很多业务团队可能对引擎并不是那么了解或者没有强烈的意愿去了解他们就可以通过这种可视化的方式拼接出一个作业。
例如可以拖一个 Kafka 的数据源进来在上面做数据过滤然后就可以拖一个 Filter 算子达到过滤逻辑后面可以再去做一些 ProjectUnion 的计算最后输出到某个地方就可以了。
对于能力稍微高一些的同学可以去做一些更高层面的计算。这里也可以实现到实时数仓的目的在里面创建一些数据源然后通过 SQL 的方式把逻辑表示出来最终把这个数据输出到某种存储。
上面是从开发层面来讲在系统层面上它其实还提供了一些其他的功能比如规则校验还有开发/测试/上线在这里可以统一管理。此外还有监控对线上跑的实时任务有很多实时指标可以通过查看这些指标来判断当前的任务是不是正常的状态。
2. 特征工程 特征工程有两方面的需求
第一个需求是实时化因为数据价值随着时间的递增会越来越低。比如某用户表现出来的观影行为是喜欢看儿童内容平台就会推荐儿童相关的广告。另外用户在看广告过程中会有一些正/负反馈的行为如果把这些数据实时迭代到特征里就可以有效提升后续的转化效果。 实时化的另一个重点是准确性之前很多特征工程是离线的在生产环节里面存在计算时的数据跟投放过程中的特征有偏差基础特征数据不是很准确因此我们要求数据要更实时、更准确。 特征工程的第二个需求是服务稳定性。 首先是作业容错比如作业在异常的时候能否正常恢复另外是数据质量在实时数据里追求端到端精确一次。
2.1 点击率预估
下面是在特征实时化里的实践首先是点击率预估的需求。 点击率预估案例的背景如上所示从投放链路上来说在广告前端用户产生观影行为前端会向广告引擎请求广告然后广告引擎在做广告召回粗排/精排的时候会拿到用户特征和广告特征。把广告返回给前端之后后续用户行为可能产生曝光、点击等行为事件在做点击率预估的时候需要把前面请求阶段的特征跟后续用户行为流里的曝光和点击关联起来形成一个 Session 数据这就是我们的数据需求。
落实到具体实践的话包括两方面
一方面是 Tracking 流里曝光、点击事件的关联另一方面是特征流跟用户行为的关联。
在实践过程中有哪些挑战
第一个挑战是数据量第二个挑战是实时数据乱序和延迟第三个挑战是精确性要求高。
在时序上来说特征肯定是早于 Tracking但是两个流成功关联率在 99% 以上的时候这个特征需要保留多久因为在广告业务中用户可以离线下载一个内容在下载的时候就已经完成了广告请求和返回了。但是后续如果用户在没有网的情况下观看这个事件并不会立马返回只有当状态恢复的时候才会有后续曝光和点击事件回传。
所以这个时候其实特征流和 Tracking 的时间概括是非常长的。我们经过离线的数据分析如果两个流的关联率达 99% 以上那么特征数据就需要保留比较长的时间目前是保留 7 天这个量级还是比较大的。 上图为点击率预测的整体架构刚才我们提到关联包括两部分
第一个部分是用户行为流里曝光跟点击事件的关联这里通过 CEP 实现。第二个部分是两个流的关联前面介绍特征需要保留 7 天它的状态较大已经是上百 TB。这个量级在内存里做管理对数据稳定性有比较大的影响所以我们把特征数据放在一个外部存储 (Hbase) 里然后和 HBase 特征做一个实时数据查询就可以达到这样一个效果。
但是因为两个流的时序本身可能是错开的就是说当曝光、点击出现的时候可能这个特征还没有到那么就拿不到这个特征。所以我们做了一个多级重试队列保证最终两个流关联的完整性。
2.2 点击率预估 - 流内事件关联 上图右边是更细的讲解阐述了流内事件关联为什么选择 CEP 方案。业务需求是把用户行为流里属于同一次广告请求并且是同一个广告的曝光跟点击关联起来。曝光之后比如 5 分钟之内产生点击作为一个正样本5 分钟之后出现的点击则抛弃不要了。
可以想象一下当遇到这样的场景通过什么样的方案可以实现这样的效果。其实在一个流里多个事件的处理可以用窗口来实现。但窗口的问题是
如果事件序列本身都在同一个窗口之内数据没有问题但是当事件序列跨窗口的时候是达不到正常关联效果的。
所以当时经过很多技术调研后发现 Flink 里的 CEP 可以实现这样的效果用类似政策匹配的方式描述这些序列需要满足哪些匹配方式。另外它可以指定一个时间窗口比如曝光和点击间隔 15 分钟。
上图左边是匹配规则的描述begin 里定义一个曝光实现曝光之后 5 分钟之内的点击后面是描述一个可以出现多次的点击within 表示关联窗口是多长时间。
在生产实践过程中这个方案大部分情况下可以关联上但是在做数据对比的时候才发现存在某些曝光点击没有正常关联到。
经过数据分析发现这些数据本身的特点是曝光跟点击的时间戳都是毫秒级别当它们有相同毫秒时间戳的时候这个事件就不能正常匹配。于是我们采用一个方案人为地对于点击事件加一毫秒进行人工错位这样就保证曝光跟点击能够成功关联上。
2.3 点击率预估-双流关联
前文提到特征数据需要保留 7 天所以状态是上百 TB。需要把数据放在一个外部存储里因此在做技术选型时对外部存储有一定的要求
首先支持比较高的读写并发能力另外它的时效性需要非常低同时因为数据要保留 7 天所以它最好具备生命周期管理能力。基于以上几个点最终选择了 HBase形成上图的解决方案。
上面一行表示通过 CEP 之后把曝光点击序列关联在一起最下面是把特征流通过 Flink 写到 HBase 里去做外部状态存储中间核心模块是用于达到两个流的关联。拿到曝光点击关联之后去查 HBase 数据如果能够正常查到就会把它输出到一个正常结果流里。而对于那些不能构成关联的数据做了一个多级重试队列在多次重试的时候会产生队列降级并且在重试的时候为了减轻对 HBase 的扫描压力重试 Gap 会逐级增加。
另外还有一个退出机制因为重试不是无限进行的。退出机制的存在原因主要包括两个点
第一点是特征数据保留了 7 天如果对应特征是在 7 天之前那么它本身是关联不到的。另外在广告业务里存在一些外部的刷量行为比如刷曝光或刷点击但它本身并没有真实存在的广告请求所以这种场景也拿不到对应特征。
因此退出机制意味着在重试多次之后就会过期然后会到重试过期的数据里。
2.4 有效点击
在有效点击场景里其实也是两个流的关联但是两个场景里的技术选型是完全不一样的。 首先看一下项目背景在网大场景里影片本身就是一个广告。用户在点击之后就会进入到一个播放页面。在播放页面里用户可以免费观看 6 分钟6 分钟之后想要继续观看需要是会员或者购买才行在这里需要统计的数据是有效点击定义是在点击之后观影时长超过 6 分钟即可。
这种场景落实到技术上是两个流的关联包括了点击流和播放心跳流。
点击流比较好理解包括用户的曝光和点击等行为从里面筛选点击事件即可。播放行为流是在用户观看的过程会定时地把心跳信息回传比如三秒钟回传一个心跳表明用户在持续观看。在定义时长超过 6 分钟的时候需要把这个状态本身做一些处理才能满足 6 分钟的条件。
在这个场景里两个流动 Gap 相对比较小而在电影里时长一般是两个多小时所以点击之后的行为Gap 基本是在三个小时以内才能完成因此这里本身的状态是相对比较小的使用 Flink 的状态管理可以达到这样的效果。
接下来我们看一个具体的方案。 从流上来看绿色部分是点击流蓝色部分是播放心跳流。
在左边的状态里面一个点击事件进来之后会对这个点击做一个状态记录同时会注册一个定时器做定期清理定时器是三个小时。因为大部分影片的时长在三小时以内如果这个时候对应的播放事件还没有一个目标状态点击事件基本就可以过期了。 在右边的播放心跳流里这个状态是对时长做累计它本身是一个心跳流比如每三秒传一个心跳过来。我们需要在这里做一个计算看它累计播放时长是不是达到 6 分钟了另外也看当前记录是不是到了 6 分钟。对应 Flink 里的一个实现就是把两个流通过 Connect 算子关系在一起然后可以制定一个 CoProcessFunction在这里面有两个核心算子。 第一个算子是拿到状态 1 的流事件之后需要做一些什么样的处理第二个算子是拿到第 2 个流事件之后可以自定义哪些功能。算子给用户提供了很多灵活性用户可以在里面做很多逻辑控制。相比很多的 Input Join用户可发挥的空间比较大。
2.5 特征工程 - 小结 针对以上案例做一个小结。现在双流管理已经非常普遍有许多方案可以选择比如 Window joinInterval join还有我们使用的 Connect CoProcessFunction。除此之外还有一些用户自定义的方案。
在选型的时候建议从业务出发去做对应的技术选型。首先要思考多个流之间的事件关系然后判断出状态是什么规模一定程度上可以从上面很多方案里排除不可行的方案。
三、Flink 使用过程中的问题及解决
1. 容错 在 Flink 内部主要是通过 Checkpoint 做容错Checkpoint 本身是对于 Job 内部的 Task 级别的容错但是当 Job 主动或异常重启时状态无法从历史状态恢复。
因此我们这边做了一个小的改进就是一个作业在启动的时候它也会去 Checkpoint 里把最后一次成功的历史状态拿到然后做初始化管理这样就达到状态恢复的效果。
2. 数据质量 Flink 本身实现端到端精确一次首先需要开启 Checkpoint 功能并且在 Checkpoint 里指定精确一次的语义。另外如果在下游比如 Sink 端它本身支持事务就可以结合两阶段提交与 Checkpoint 以及下游的事务做联动达到端到端精确一次。
在上图右边就是描述了这个过程。这是一个预提交的过程就是 Checkpoint 协调器在做 Checkpoint 的时候会往 Source 端注入一些 Barrier 数据每个 Source 拿到 Barrier 之后会做状态存储然后把完成状态反馈给协调器。这样每个算子拿到 Barrier其实是做相同的一个功能。
到 Sink 端之后它会在 Kafka 里提交一个预提交标记后面主要是 Kafka 本身事务机制来保证的。在所有的算子都完成 Checkpoint 之后协调器会给所有的算子发一个 ACK发送一个确认状态这时候 Sink 端做一个提交动作就可以了。
3. Sink Kafka 在之前的实践中我们发现下游 Kafka 增加分区数时新增分区无数据写入。
原理是 FlinkKafkaProducer 默认使用 FlinkFixedPartitioner每个 Task 只会发送到下游对应的一个 Partition 中如果下游 Kafka 的 Topic 的 Partition 大于当前任务的并行度就会出现该问题。
解决办法有两个
第一个办法是用户自定义一个 FlinkKafkaPartitioner另一个办法是默认不配置默认轮询写入各个 Partition。
4. 监控加强 对于运行中的 Flink 作业我们需要查看它本身的一些状态。比如在 Flink UI 里面它的很多指标都是在 Task 粒度没有整体的效果。
平台这边对这些指标做了进一步的聚合统一在一个页面里面展示。
从上图可以看到展示信息包括反压状态时延情况以及运行过程中 JobManager 和 TaskManage 的 CPU / 内存的利用率。另外还有 Checkpoint 的监控比如它是否超时最近是否有 Checkpoint 已经失败了后面我们会针对这些监控指标做一些报警通知。
5. 监控报警 当实时任务运营异常的时候用户是需要及时知道这个状态的如上图所示有一些报警项包括报警订阅人、报警级别下面还有一些指标根据前面设置的指标值如果满足这些报警策略规则就会给报警订阅人推送报警报警方式包括邮件、电话以及内部通讯工具从而实现任务异常状态通知。
通过这种方式当任务异常的时候用户可以及时知晓这个状态然后进行人为干预。
6. 实时数据生产
最后总结一下爱奇艺广告业务在实时链路生产上面的关键节点。 我们的实时是从 2016 年开始起步当时主要功能点是做一些指标实时化使用的是 SparkStreaming2018 年上线了点击率实时特征2019 年上线了 Flink 的端到端精确到一次和监控强化。2020 年上线了有效点击实时特征同年10月逐步推进实时数仓的改进把 API 生产方式逐渐 SQL 化2021 年 4 月进行流批一体的探索目前先把流批一体放在 ETL 实现。
之前我们的 ETL 实时跟离线是分别做的通过批处理的方式然后换到 Hive 表里边后面跟的是离线数仓。在实时里经过实时 ETL放到 Kafka 里边然后去做后续的实时数仓。
先在 ETL 做流批一体的第一个好处是离线数仓时效性提升因为数据需要做反作弊所以我们给广告算法提供基础特征的时候反作弊之后的时效性对于后续整体效果的提升是比较大的所以如果把 ETL 做成统一实时化之后对于后续的指导意义非常大。
ETL 做到流批一体之后我们会把数据放在数据湖里面后续离线数仓和实时数仓都可以基于数据湖实现。流批一体可以分为两个阶段第一阶段是先把 ETL 做到一体另外报表端也可以放在数据湖里边这样我们的查询服务可以做到一个更新的量级。因为之前需要离线表跟实时表做一个 Union 的计算在数据湖里面我们通过离线和实时写一个表就可以实现了。
四、未来规划 关于未来规划 首先是流批一体这里包括两个方面 第一个是 ETL 一体目前已经是基本达到可线上的状态。第二个是实时报表 SQL 化和数据湖的结合。另外现在的反作弊主要是通过离线的方式实现后面可能会把一些线上的反作弊模型转成实时化把风险降到最低。
原文链接 本文为阿里云原创内容未经允许不得转载。