快手实时数仓保障体系研发实践
01业务特点及实时数仓保障痛点
快手最大的业务特点就是数据量大。每天入口流量为万亿级别。对于这么大的流量入口,需要做合理的模型设计,防止重复读取的过度消耗。另外还要在数据源读取和标准化过程中,极致压榨性能保障入口流量的稳定执行。第二个特点是诉求多样化。快手业务的需求包括活动大屏的场景、2B 和 2C 的业务应用、内部核心看板以及搜索实时的支撑,不同的场景对于保障的要求都不一样。如果不做链路分级,会存在高低优先级混乱应用的现象,对于链路的稳定性会产生很大的影响。此外,由于快手业务场景的核心是做内容和创作者的 IP,这就要求我们构建通用维度和通用模型,防止重复烟囱建设,并且通过通用模型快速支撑应用场景。第三个特点是活动场景频繁,且活动本身有很高的诉求。核心诉求主要为三个方面:能够体现对公司大盘指标的牵引能力、能够对实时参与度进行分析以及活动开始之后进行玩法策略的调整,比如通过对红包成本的实时监控快速感知活动效果。活动一般都会有上百个指标,但只有 2-3 周的开发时间,这对于稳定性的要求就很高。最后一个特点是快手的核心场景。一个是提供给高管的核心实时指标,另外一个是提供给 C 端的实时数据应用,比如快手小店、创作者中心等。这对数据精度的要求极其高,出现问题需要第一时间感知并介入处理。
以上要素构成了快手实时数仓建设和保障场景的必要性。
在实时数仓保障的起始阶段,我们借鉴了离线侧的保障流程和规范,按照生命周期划分了三个阶段:研发阶段、生产阶段和服务阶段。
研发阶段构建了模型设计规范、模型开发规范以及发布的 checklist。生产阶段主要构建底层监控能力,对于时效性、稳定性、准确性几个方面进行监控,并且依照监控能力进行 SLA 优化和治理提升。服务阶段明确了上游对接的服务标准和保障级别,以及对于整个服务的价值评估。
但是相比于离线,实时的学习成本颇高,完成以上建设后,各个结算依然存在几个问题:
研发阶段:Flink SQL 的学习曲线相比于 Hive SQL 更高,容易在开发阶段引入隐患。另外,实时计算场景下,活动出现洪峰时能否快速消费,也是一个未知数。最后,DWD 层的重复消费对于实时侧的资源挑战也很大,在选择数据源和依赖关系时需要考虑资源问题。生产阶段:state 没有清理机制会导致状态变大、作业频繁失败。另外高优先级和低优先级部署需要机房隔离,因此需要在上线前就安排好,上线后再进行调整,成本会比离线高很多。服务阶段:对于一个实时任务,最无法接受的就是作业流程失败、重启,导致数据重复或者曲线掉坑的问题。为了避免这类问题,需要有标准化的方案,而离线大概率可以保证重启后数据一致性。
抽象来看,实时数仓相比于离线,还存在几个保障难点,具体体现在以下几个方面:
高时效性。相比于离线的执行时间,实时情况下,延迟分钟级就要介入运维,对时效性要求很高。复杂性。主要体现在两个方面:一方面数据不是导入即可查,数据逻辑验证的难度更高;另外一方面,实时大多是有状态,服务发生问题的时候状态不一定能够被完整保存,会存在很多无法复现的 bug。数据流量大。整体的 QPS 比较高,入口流量级别在亿级。问题随机性。实时数仓发生问题的时间点更加随机,没有规律可循。开发能力良莠不齐。如何保证通用场景的开发方案统一,防止因开发方案不同而产生不可控的问题。
02快手实时数仓保障体系架构
基于以上保障的难度,我们设计了两条思路来解决,主要分为两个方面:
一方面是以开发生命周期为基础的正向保障思路,确保每一个生命周期都有规范和方案指导,标准化 80% 的常规需求。另一方面是以故障注入和场景模拟为基础的反向保障思路,通过场景模拟和故障注入,确保保障措施真正落地并符合预期。2.1 正向保障
正向保障的整体思路如下:
开发阶段主要做需求调研,针对开发过程中基础层如何开发、应用层如何开发进行标准化处理,可以解决 80% 的通用需求,剩余 20% 的个性化需求通过方案评审的方式来满足,同时不断从个性化需求中沉淀标准化方案。测试阶段主要做质量验证和离线侧对比以及压测资源预估。自测阶段主要通过离线实时的一致性对比、server 看板和实时结果对比来保障整体准确性。上线阶段主要针对重要任务上线需要准备的预案,确认上线前动作、上线中部署方式和上线后的巡检机制。服务阶段主要是针对于目标做监控和报警机制,确保服务是在 SLA 标准之内的。最后是下线阶段,主要做资源的回收和部署还原工作。
快手的实时数仓分为三个层次:
第一,DWD 层。DWD 层逻辑侧比较稳定且很少有个性化,逻辑修改分为三种不同的格式数据:客户端、服务端和 Binlog 数据。第一项操作是拆分场景,由于实时数仓没有分区表的逻辑,所以场景拆分的目的是生成子 topic,防止重复消费大 topic 的数据。第二个操作就是字段标准化,其中包括纬度字段的标准化处理、脏数据的过滤、IP 和经纬度一一映射关系的操作。第三是处理逻辑的维度关联,通用维度的关联尽量在 DWD 层完成,防止下游过多流量依赖导致维表压力过大,通常维表是通过 KV 存储 二级缓存的方式来提供服务。第二,DWS 层。这里有两种不同的处理模式:一是以维度和分钟级窗口聚合为基础的 DWS 层,为下游可复用场景提供聚合层的支撑;二是单实体粒度的 DWS 层数据,比如原始日志里核心用户和设备粒度的聚合数据,可以极大地减少 DWD 层大数据量的关联压力,并能够更有效地进行复用。DWS 层数据也需要进行维度扩充,由于 DWD 层数据量过大,无法完全 cover 维度关联的场景,因此维度关联 QPS 过高并有一定延时的需求,需要在 DWS 层完成。第三,ADS