乐趣区

关于Flink:Flink-在爱奇艺广告业务的实践

本文整顿自爱奇艺技术经理韩红根在 5 月 22 日北京站 Flink Meetup 分享的议题《Flink 在爱奇艺广告业务的实际》,内容包含:

  1. 业务场景
  2. 业务实际
  3. Flink 应用过程中的问题及解决
  4. 将来布局

一、业务场景

实时数据在广告业务的应用场景次要能够分为四个方面:

  • 数据大屏: 包含曝光、点击、支出等外围指标的展现,以及故障率等监控指标;
  • 异样监测: 因为广告投放的链路比拟⻓,所以如果链路上产生任何稳定的话,都会对整体的投放成果产生影响。除此之外,各个团队在上线过程中是否会对整体投放产生影响,都是通过异样监测零碎可能观测到的。咱们还可能观测业务指标走势是否正当,比方在库存失常的状况下,曝光是否有不同的稳定状况,这能够用来实 时发现问题;
  • 数据分析: 次要用于数据赋能业务倒退。咱们能够实时剖析广告投放过程中的一些异样问题,或者基于以后的投放成果去钻研怎么优化,从而达到更好的成果;
  • 特色工程: 广告算法团队次要是做一些模型训练,用于反对线上投放。技术特色最后大部分是离线,随着实时的倒退,开始把一些工程转到实时。

二、业务实际

业务实际次要分为两类,第一个是实时数仓,第二个是特色工程。

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 分钟,也就是说 4:00 这个工夫点的指标的就包含了 4:00~4:03 的数据,4:03 包含了 4:03~4:06 的数据,其实就是指一个工夫窗口的数据,什么时候是对外可见的。因为在实时计算里,数据一直进来,4:00 的工夫窗口的数据从 4:00 开始,指标就曾经开始产生了。随着工夫叠加,指标一直回升,最初趋于稳定。咱们基于工夫窗口指标的变化率,来判断它是否趋于稳定。

但如果只是基于这个点来看,那么它还存在肯定的弊病。

因为这个后果表的计算链会依赖很多个计算工作,如果这个链路下面哪个工作呈现问题,可能会导致以后的指标尽管走势曾经趋于失常,然而最终并不残缺。所以在这根底之上,咱们又引入了实时计算工作状态,在指标趋于稳定的时候,同时去看生产链路上这些计算工作是否失常,如果是失常的话,示意工作自身工夫点的指标曾经稳固,能够对外提供服务。

如果计算有卡顿、沉积,或者曾经有异样在重启过程中,就须要持续期待迭代解决。

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 算子达到过滤逻辑,前面能够再去做一些 Project,Union 的计算,最初输入到某个中央就能够了。

对于能力略微高一些的同学,能够去做一些更高层面的计算。这里也能够实现到实时数仓的目标,在外面创立一些数据源,而后通过 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 join,Interval 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 年开始起步,过后次要性能点是做一些指标实时化,应用的是 SparkStreaming;
  • 2018 年上线了点击率实时特色;
  • 2019 年上线了 Flink 的端到端准确到一次和监控强化。
  • 2020 年上线了无效点击实时特色;
  • 同年 10 月,逐步推进实时数仓的改良,把 API 生产方式逐步 SQL 化;
  • 2021 年 4 月,进行流批一体的摸索,目前先把流批一体放在 ETL 实现。

之前咱们的 ETL 实时跟离线是别离做的,通过批处理的形式,而后换到 Hive 表里边,前面跟的是离线数仓。在实时里,通过实时 ETL,放到 Kafka 里边,而后去做后续的实时数仓。

先在 ETL 做流批一体的第一个益处是离线数仓时效性晋升,因为数据须要做反作弊,所以咱们给广告算法提供根底特色的时候,反作弊之后的时效性对于后续整体成果的晋升是比拟大的,所以如果把 ETL 做成对立实时化之后,对于后续的指导意义十分大。

ETL 做到流批一体之后,咱们会把数据放在数据湖外面,后续离线数仓和实时数仓都能够基于数据湖实现。流批一体能够分为两个阶段,第一阶段是先把 ETL 做到一体,另外报表端也能够放在数据湖里边,这样咱们的查问服务能够做到一个更新的量级。因为之前须要离线表跟实时表做一个 Union 的计算,在数据湖外面,咱们通过离线和实时写一个表就能够实现了。

四、将来布局

对于将来布局:

  • 首先是流批一体,这里包含两个方面:

    • 第一个是 ETL 一体,目前曾经是根本达到可线上的状态。
    • 第二个是实时报表 SQL 化和数据湖的联合。
  • 另外,当初的反作弊次要是通过离线的形式实现,前面可能会把一些线上的反作弊模型转成实时化,把危险降到最低。
退出移动版