分享好友 站长动态首页 网站导航

快手实时数仓保障体系研发实践

2022-06-28 10:03 · 头闻号数据库

摘要:本文整理自快手实时计算数据团队技术专家李天朔在 Flink Forward Asia 2021 实时数仓专场的演讲。主要内容包括:

01业务特点及实时数仓保障痛点

快手最大的业务特点就是数据量大。每天入口流量为万亿级别。对于这么大的流量入口,需要做合理的模型设计,防止重复读取的过度消耗。另外还要在数据源读取和标准化过程中,极致压榨性能保障入口流量的稳定执行。

第二个特点是诉求多样化。快手业务的需求包括活动大屏的场景、2B 和 2C 的业务应用、内部核心看板以及搜索实时的支撑,不同的场景对于保障的要求都不一样。如果不做链路分级,会存在高低优先级混乱应用的现象,对于链路的稳定性会产生很大的影响。此外,由于快手业务场景的核心是做内容和创作者的 IP,这就要求我们构建通用维度和通用模型,防止重复烟囱建设,并且通过通用模型快速支撑应用场景。

第三个特点是活动场景频繁,且活动本身有很高的诉求。核心诉求主要为三个方面:能够体现对公司大盘指标的牵引能力、能够对实时参与度进行分析以及活动开始之后进行玩法策略的调整,比如通过对红包成本的实时监控快速感知活动效果。活动一般都会有上百个指标,但只有 2-3 周的开发时间,这对于稳定性的要求就很高。

最后一个特点是快手的核心场景。一个是提供给高管的核心实时指标,另外一个是提供给 C 端的实时数据应用,比如快手小店、创作者中心等。这对数据精度的要求极其高,出现问题需要第一时间感知并介入处理。

以上要素构成了快手实时数仓建设和保障场景的必要性。

在实时数仓保障的起始阶段,我们借鉴了离线侧的保障流程和规范,按照生命周期划分了三个阶段:研发阶段、生产阶段和服务阶段。

但是相比于离线,实时的学习成本颇高,完成以上建设后,各个结算依然存在几个问题:

抽象来看,实时数仓相比于离线,还存在几个保障难点,具体体现在以下几个方面:

02快手实时数仓保障体系架构

基于以上保障的难度,我们设计了两条思路来解决,主要分为两个方面:

2.1 正向保障

正向保障的整体思路如下:

  1. 开发阶段主要做需求调研,针对开发过程中基础层如何开发、应用层如何开发进行标准化处理,可以解决 80% 的通用需求,剩余 20% 的个性化需求通过方案评审的方式来满足,同时不断从个性化需求中沉淀标准化方案。
  2. 测试阶段主要做质量验证和离线侧对比以及压测资源预估。自测阶段主要通过离线实时的一致性对比、server 看板和实时结果对比来保障整体准确性。
  3. 上线阶段主要针对重要任务上线需要准备的预案,确认上线前动作、上线中部署方式和上线后的巡检机制。
  4. 服务阶段主要是针对于目标做监控和报警机制,确保服务是在 SLA 标准之内的。
  5. 最后是下线阶段,主要做资源的回收和部署还原工作。

快手的实时数仓分为三个层次:

基于以上设计思路,不难发现针对 DWD 和 DWS 的拆流的逻辑、字段清洗标准化和维度关联,都是针对不同格式但逻辑相同。可以把基础的逻辑开发成模板化 SDK,后续相同逻辑都使用相同的 SDK API 方法。这样有两个好处,重复的逻辑不需要再复制一遍代码,一些优化的经验和教训也沉淀在了模板里。

针对 ADS 层数据,我们通过业务需求沉淀出诸多解决方案,比如多维度的 PV/UV 如何计算、榜单如何计算、指标卡的 SQL 如何表达以及分布类存在回撤的场景如何产出。

SQL 本身上手快、效率高,能大规模简化开发时间,但它的执行效率相比于 API 有一定的劣势,所以针对于基础储层和 DWS 层大流量场景,我们还是使用 API 进行开发,应用层通过 SQL 进行开发。

快手的大部分活动中,业务最关注的指标是某些维度下参与人数、领取金钱的累计曲线,并且希望能够产出一个每分钟计算 0 点到当前时刻的曲线,这类指标开发覆盖了 60% 左右的活动侧需求。那么开发过程中有哪些难点呢?

用常规的滚动窗口 + 自定义状态的计算对数据进行去重有一个弊端:如果窗口乱序较大,会造成数据丢失严重,影响数据的准确性。如果希望数据更准,就要承受更大的数据延迟,而想要延迟低一些就可能存在数据不准确的情况。此外,异常情况下会存在数据从某一个时间点开始回溯的场景,回溯场景下增大吞吐量会因为取最大时间戳导致中间结果丢失。

为了解决这个问题,快手自研了渐进式窗口的解决方案,它存在两个参数,天级别的窗口和输出的分钟步长。整体的计算分为两个部分,首先产出一个天级别的窗口,读取数据源按照 key 进行分筒,把 key 相同的数据分到同一个筒内,然后按照事件时间进行 watermark 推进,超过对应的窗口步长就会触发窗口计算。

如上图所示, key=1 的数据分到同一个 task,task watermark 更新到超过步长产生的小窗口之后会合并产出 bitmap 和 pv 的计算结果,并发送给下游数据,按照 servertime 落到对应的窗口,并且通过 watermark 机制进行触发。在 global window 进行合筒操作时,会把分筒的结果进行累加和去重,最终输出结果。这样如果存在乱序和晚到的数据就不会丢弃数据,而是会记录延迟之后的时间节点,更好地保证了数据的准确性,整体的数据差异从 1% 下降到 0.5%。

另外一方面,watermark 超过步长 window 窗口就触发计算,曲线延迟可以控制在一分钟以内完成,更好地保证了时效性。最后通过 watermark 控制步长的窗口输出可以保障步长窗口每个点都进行输出,输出曲线最大程度保障了平滑性。

上图是一个具体的 SQL 案例,内部是一个按照 deviceID 分筒,然后构建 cumulate window 的过程。window 有两个部分,一个是按天累计的计算参数,另外一个是 watermark 划分窗口的参数,外层会对不同分筒产生的指标进行聚合计算。

在上线阶段,首先是做好时间线的保障规范,包括时间、操作人、预案内容、操作记录和检查点。

  1. 活动前,部署任务确保没有计算热点、check 参数是否合理、观察作业情况以及集群情况;
  2. 活动中,检查指标输出是否正常、任务状态巡检以及遇到问题的故障应对和链路切换;
  3. 活动后,下线活动任务、回收活动资源、恢复链路部署及复盘。

这里的链路是从 Kafka 数据源开始导入到 ODS、DWD、DWS 层,针对 C 端用户会导入到 KV 存储里,针对分析类场景会导入到 ClickHouse,最后生成数据服务。我们将任务分成 4 个等级,p0 ~ p3。

服务阶段主要分成 4 个层次:

准确性的目标具体包括以下三部分:离线实时指标一致性用来保障整体的数据处理逻辑是正确的,OLAP 引擎和应用接口一致性用来保证服务的处理逻辑是正确的,指标逻辑错误报警用来保障业务逻辑是正确的。

2.2 反向保障

线上活动正常的开发测试很难模拟真正的线上环境和压测进度,所以反向保障的重点是要测试活动流量预期的情况下能否扛住洪峰,以及出现故障时如何处理?

核心思路是通过压测演练来模拟活动洪峰的真实场景。首先通过单作业压测确定每个作业的资源分布和作业所在集群的编排方式,通过全链路压测确保集群资源使用在一定水位并且平稳消费洪峰,不会过大或过小。其次,进行容灾建设,主要针对作业失败、消费延迟、机房故障等提出了一些保障手段。然后,通过演练的方式,确保这些手段可以被正常使用并且能够达到预期效果。最后,针对演练的预期和目标进行复盘和链路风险的改进。

我们构建了自己的压测链路,上面是正常的链路,下面是压测链路。首先读取线上 topic 的数据作为压测链路的初始数据源,利用 rate limit 算法进行流量控制。比如有 4 个 task,希望获得 1 万 QPS,那么每个 task 生成的 QPS 会限制在 2500,并且生成数据的过程中会利用人群包修改对应的 user 和生成的时间戳,模拟当天真实的用户数。

读取压测的数据源 topic 并经过作业处理生成新的 topic 后,如何判断压测是否真正通过,有三个标准:第一,确保作业输入读取延迟为毫秒级,且作业本身无任何反压。第二,CPU的利用率不超过整体资源的 60%,保障集群有空余 buffer。第三,计算结果和人群包保持一致,证明逻辑是正确的。

经过单作业压测之后,我们可以得到很多信息用于指导后续工作。比如,可以证明活动能在预期流量下保障 SLA,可以发掘作业性能瓶颈,指导优化达成对应标准以及场景 benchmark,方便低优作业的资源部署。

完成单作业压测之后,还是无法判断所有作业是否完全启动。对于 Flink 机房整体的 CPU、IO 还有 memory 压力等情况,我们可以把每个作业按照压测目标值启动起来,观察整体作业和集群的表现。

那么如何判断全链路压测是否通过呢?也有三个标准:

通过全链路压测之后,可以证明活动在预期流量的峰值情况下能够保障 SLA,确保 QPS 作用下作业的资源编排情况,提前确定每个作业所需的资源和部署参数,确保每个数据源上游最大流量信息,为后续的限流保障提供基础。

故障演练有两种方式:

容灾建设分为两个部分,链路的故障容灾和链路的容量保障。

链路的故障容灾保障核心是解决单机房和单作业失败恢复时间长的问题和服务的稳定性问题。Kafka 本身可以做双机房容灾,生成流量会写入到两个机房的 Kafka,出现单机房故障时会自动把流量切换到另外一个机房,而且保证 Flink 作业无感知。另外一方面机房故障恢复之后,可以自动探测 Kafka 机房的状态加入流量。

同样,容灾策略也适用于 OLAP 引擎。针对于 Flink 任务,我们热备部署了双链路,主备链路同逻辑,某个机房出现故障时可以直接将应用侧 OLAP 引擎切换到另一个链路使用,保障应用端对于故障是无感知的。

链路容量的保障是为了解决两个问题:如果活动流量超过预期很多,如何保障稳定性?如果产生了 lag,评估需要多久能够追赶消费延迟?

根据之前全链路压测的结果,能够得到每个任务入口的最大流量,并且将这个流量值作为作业的最大限流值,当活动流量超过了预期很高,数据源侧会触发读取限流,Flink 作业会按照压测最大负载执行。这个时候作业消费虽有延迟,但是能够保护链路中其他作业正常运行。并且在洪峰结束后,可以根据 lag 数据和入口流量计算出作业恢复正常需要的时间,这个是链路的故障容灾和容量保障的核心措施。

03春节活动实时保障实践

春节活动有以下几个需求:

春节活动的整体方案分为正向和反向的保障措施。

正向保障措施的基础是监控报警体系,分为两个部分。一方面是对时效性、准确性、稳定性做 SLA 目标报警建设。另外一方面是基于链路的监控体系建设,包括链路监控、链路依赖的服务可用性监控以及集群资源监控。

在监控体系的基础之上,正向保障措施主要是做开发阶段、测试阶段和上线阶段的标准化。开发阶段 80% 的需求通过标准化模板来解决,而 20% 的剩余需求可以通过评审的方式解决风险问题。测试阶段通过对比的方式保证逻辑准确性,上线阶段做分期部署和任务巡检。

反向保障措施需要构建两个基础能力。第一是压测能力,主要是通过单作业压测确定任务性能瓶颈,从而更好地指导优化;通过全链路压测确定作业是否能够扛过洪峰,并为容灾能力提供数据基础。容灾能力主要是通过多机房部署、限流、重试、降级,确保在有故障的情况下有对应的方案。

最后通过故障演练的方式,一方面引入各个组件的故障定位,另一方面模拟流量峰值的情况,确保压测和容灾能力真正得以执行。

最后在上线阶段通过时间线预案保障活动前、中、后操作步骤都有迹可循,活动结束后对于项目进行复盘,发现问题并反馈到正反两个方向的保障体系能力建设。

春节活动的实践获得了巨大的成功。时效性方面,面对上亿级别的流量洪峰,大屏核心链路指标卡秒级延迟,曲线类一分钟内延迟,单个任务处理数据量在万亿级别之上,在流量高峰期是秒级延迟。准确性方面,核心链路离线和实时任务差异 0.5% 以内,大促活动过程无数据质量问题,有效使用 FlinkSQL 渐进式窗口开发,大幅度降低窗口丢失导致的精度损失,数据差异从 1% 降到 0.5%。稳定性方面,核心链路依赖组建双机房容灾、Flink 集群热备双链路部署,出现问题秒级切换,压测和容灾能力的沉淀,为以后的活动保障体系建设奠定基础。

04未来规划

基于对现有的方法论和应用场景的思考,我们对未来规划也做了延伸。

免责声明:本平台仅供信息发布交流之途,请谨慎判断信息真伪。如遇虚假诈骗信息,请立即举报

举报
反对 0
打赏 0
更多相关文章

评论

0

收藏

点赞