干货|在字节,大规模埋点数据治理这么做!

技术

picture.image

字节跳动内部统一的埋点平台——流量平台,已经覆盖了字节内部2000 多个应用,管理埋点(事件)数20万,每天产生的埋点数据量超过万亿,每年能给公司节省的成本超亿元。本文整理自字节跳动数据平台—— 流量平台技术负责人Cody在火山引擎开发者社区 Meetup 第四期演讲。

埋点是什么?埋点主要是描述用户在 APP 内触发的一系列行为,包括点击、侧滑等。基于这些行为,我们可以进行行为分析、个性化推荐、精准营销等很多事情。

埋点主要描述的是哪些数据?

  • Who: 谁操作的数据
  • When: 什么时候操作的数据
  • Where: 在哪些页面、模块的数据
  • How: 用户如何操作的
  • What: 有哪些附加信息

因为本文介绍的是埋点治理,所以这里再介绍一下什么是数据治理。

数据治理是指在数据的生命周期内,对其进行管理的原则性方法,其目标是为了确保数据的安全、及时、准确、可用和易用。数据总是会变得无效甚至无用,因此就涉及到对存量数据的治理。 但这里要强调一下,数据治理不只针对存量数据,更重要的是对增量数据的治理,通过一系列手段,能保证数据从源头开始就是正确的。

此外,所有的治理都有具体的落地内容, 一个稳定的治理链路是所有数据治理的基石

下面就为大家介绍字节跳动是如何治理埋点数据的。

DATA

字节跳动流量平台

流量平台是字节跳动内部统一的埋点平台,覆盖埋点数据定义、采集、生产、应用、治理等埋点全生命周期。 当前,流量平台已经覆盖了 2000 多个应用,管理埋点(事件)数 20 万,每天产生的埋点数据量超过万亿,每年能给公司节省的成本超亿元。

picture.image

图注:字节跳动流量平台的产品概念图

字 节跳动流量平台 主要分为几块:

  • 埋点内容: 这是用户接触最多的一块,包括埋点生命周期的设计、开发、验证、上线、使用、乃至下线。
  • 埋点治理: 指的是狭义的对存量数据的治理。涉及成本、SLA 等的治理。
  • 链路侧: 包含埋点的收集、处理和订阅的全链路,平台目前支持对 iOS、Android 等全端数据的收集。平台已经跟下游使用流量数据的应用进行打通,用户可以订阅数据。
  • 链路根基: 即自研的动态实时计算平台,也是整个平台的核心技术,它能够支撑起 字节跳动万亿+的实时数据 的处理。

DATA

埋点内容解决方案

picture.image

埋点内容主要管理埋点生命周期,这里要着重强调一下上图中心位置的埋点模型其实非常重要,因为埋点模型设计的好坏直接影响到埋点的设计、开发、测试甚至使用。

picture.image

埋点内容用户痛点

埋点内容的用户主要是有两大类:埋点消费者和埋点生产者。对于埋点消费者来说,存在如下痛点:

  • 查找难度大: 埋点数量非常多,找不到自己想要的埋点。
  • 使用难度高: 找到埋点之后,用户也很可能不清楚指标埋点口径。
  • 埋点难信任: 当数据不符合预期时,不确定埋点数据是否可用。

对于埋点生产者来说,也有一些痛点:

  • 生产链路长: 各方信息对齐、流程推动难度大;
  • 模型落地难: 不知如何设计、不知是否符合规范;
  • 缺乏工具支持: 设计、开发、测试纯白手起家。

那怎么去解决用户的这些痛点呢?首先我们要弄清楚埋点的第一站是什么。很多公司都有埋点系统,对于大部分公司而言,埋点的第一站是埋点录入。但是大家会发现,埋点录入并不是一切的源头,埋点设计才是。埋点设计是第一手的资料,根据埋点的设计文稿可以将用户的需求梳理得非常细致。而埋点录入是第二手甚至是第 N 手资料,录入的信息肯定会有丢失,并且只能进行一些基本的校验,满足基本的准确性。

其次,如果没有资产的辅助设计,每一个埋点录入都要从 0 到 1 去实现一遍。但是埋点设计通过资产辅助设计可以变得很简单。因此,我们认为埋点设计才是 the single source of truth,这是我们整体设计的核心。

下面来看看用户如何在我们的系统设计埋点。

字节跳动流量平台的产品辅助设计 基于灵活的模型支持、设计资产积累、设计辅助,可以方便每一个用户定义高质量数据,让用户愿意在系统进行设计和评审。

设计完埋点,我们在埋点开发上也有对应的工具来服务来发。下面是我们的一段演示:

当用户要设计埋点时,可以通过 ID 找到要开发的埋点,通过点击即可插入代码。同时,系统支持 VSCode 等主流编辑器,针对不同语言和代码风格自定义代码模版,还有类型校验、编辑切换等。

picture.image

埋点测试

埋点测试比 QA 要难很多,看的是一串数字、类型的值等。 在字节跳动流量平台系统中,可以依托埋点设计中的规则辅助测试,针对类型、取值、必填等自动验证,并且可以一键生成报告。

我们是怎么去做好测试这件事的呢?重点还是前面提到的做好埋点设计。只有设计周全,才能积攒足够的规则进行自动化测试,因此埋点设计方案非常重要。

埋点设计者会在方案设计时制定一系列的约束规则,我们会依托这些约束规则生成一系列相匹配的测试用例,并在测试过程中进行自动匹配、测试。

埋点测试时,测试者手机扫码即可将服务器和浏览器建立连接,在 App 上操作后,流量平台可以实时接收到对应的埋点数据。因为已经有测试用例,规则执行引擎便可以自动匹配执行并得到结果,再通过验证结果推送服务实时推送至浏览器。

埋点测试后,用户可以通过报告生成器可以一键生成报告,发送给 RD 进行修改或者 DA 进行验收。这样就完成了整个测试流程。

picture.image

picture.image

埋点存量治理

在生成了大量的埋点之后,我们需要进行存量埋点数据的治理,具体涉及 SLA、成本、合规以及数据质量等方面。 为什么还要进行存量埋点数据的治理呢? 我们有这样一些观点:

  1. 数据不一定都是重要的。 因为业务都不一定总是重要的。
  2. 数据并不总是有用的。 比如活动下线了,埋点就要下线,否则付出了成本却没有收益。
  3. 数据不一定总是合规的。 随着数据隐私的重要性越来越高,合规要求也在不断更新变动。

对于存量埋点数据的治理,也有一些痛点。对于治理负责方来说,数据越来越多,而对数据的实时性要求却越来越高;随着数据量暴增,成本也急剧增加,SLA 等级越来越慢;用户隐私也越来越重要。对于治理实施方来说,他们可能不敢治理,不愿治理,也不懂治理。

我们梳理了用户的需求,发现是这样几层:

  • 用户层: 自动化识别埋点是否有用,流程化引导埋点的分级和下线。
  • 统计层: 做到数字化、货币化,治理大盘清晰可知,埋点成本准确无误。
  • 甄别层: 通过的血缘图谱,对实时统计、离线报表、行为分析、推荐系统等做实时决策。
  • 执行层: 从 APP 端到数仓全流程,强兜底。
  • 链路层: 需要高效、稳定、完整的链路方案解决治理难题。

针对这些需求,我们是怎么做的呢?

picture.image

埋点分级/无用埋点甄别

埋点血缘和离线血缘抽取不太一样。 离线血缘是点与点之间的血缘,但埋点血缘关注的是内容与点 的血缘,它需要知道一张表的哪些行的信息有用。 这是完全不同的一个领 域,没有任何前人的经验可以借鉴,我们在埋点血缘做了几个方面的事情:

  • 离线处理: 通过 SQL 解析,计算埋点与离线表的血缘;
  • 实时处理: 利用埋点链路优势,掌握实时分流血缘关系;
  • 即时分析: 与行为分析、SQL 临时查询系统打通;
  • 推荐系统: 利用数据清洗链路优势,解耦推荐血缘。

在埋点分级上,我们以性能埋点为突破口,给予匹配的 SLA 和 TTL 配置。

DATA

埋点链路解决方案

下面着重介绍一下我们的埋点链路解决方案。首先我们还是来看下埋点链路用户的需求是什么。对于非技术的运营、分析师同学,他们需要清楚自己:

  • 需要什么样的数据: 是埋点数据还是展现数据?
  • 需要哪些数据: 最好能对不同来源不同时效性的数据进行可视化过滤、清洗。
  • 需要在哪里用这些数据: 是实时报表,还是行为分析,还是推荐?

picture.image

埋点链路的挑战

在埋点链路设计上我们也遇到了一些挑战:

  • 大数据量下的稳定性: 埋点数据在字节跳动是核心数据,其稳定性非常重要。
  • 低延迟实时处理: 尤其对于推荐,实时性要求非常高。
  • 分级构建+下线, 这里分几块内容:

数据接入 :我们提供全栈 SDK 接入,还在 SDK 内置了管控的机制,利用各个 APP 内终端计算的能力,大大节省成本;而且根据合规要求不能上报的埋点就可以直接在 SDK 端丢弃掉。

数据收集 : 数据收集一般是提供 HTTP 接口,将上报的数据存到消息队列。而埋点数据量特别大,于是我们进行了埋点聚合,将埋点的 Event 数据聚合成 Applog 数据一起上报。数据进入到 Applog 后通过自研的实时数据处理平台来解析。

picture.image

实时动态引擎处理

picture.image

上图是我们自研的实时数据平台架构,该平台主要解决两方面的问题:

  • 实时处理: 快速处理大量数据;
  • 动态化: 字节跳动服务规模巨大,重启时间过长会导致下游断流,因此我们的实时领域里不接受重启。此外,逻辑有任何修改都要重启,在大量的业务和逻辑下这是不可能实现的。所以该平台一定要做到动态化。

动态实时处理引擎在收到实时数据的 Applog 后将其解析成真正的埋点数据。再通过数据加工,可以转换为其他的(甚至自定义的)数据格式,最后通过数据订阅推送到各应用。

第二种模式是分级。 在埋点数据被解析以后,我们会打上标记,然后 dump 到 hdfs 不同的路径下。后续 Hive 进行构建的时候可以区分优先级,优先级高的进入高优队列。Hive 的数据也是分区的,分区的数据可以制定不同的 TTL。这样,数据的 TTL 和 SLA 就都能分级了。

第三是强保证。 在埋点数据下线前,先将要下线的数据分流到 pre-discard Hive 表中暂存 30 天。如果在这段时间里没有问题,30 天之后就可以直接下线。

现在, 该引擎的处理逻辑、拓扑、函数以及 RPC 都可以做到动态化 。用户对于上游而言,一般是写 SQL 或者进行界面化操作。因为用户不懂如何处理,我们就需要特定的模型让用户进行适配。于是我们用声明式表达建立统一的逻辑模型让用户直接适配。在引擎上我们还能以插件化的形式支持 Flink、Pyjstorm、TCE 等多种运行时平台,业务方基于视图表达可以定制化支持业务场景。

Map 计算模型

下面介绍下该引擎的逻辑动态性。我们使用的是简单的 map 模型。

picture.image

数据进来后判断是否是需要的,过滤清洗之后需要的数据进入下游,不需要的数据就丢弃掉。基于 Groovy 语言的热加载,将语言转换成可执行的逻辑。

拓扑重构

字节跳动的业务新增速度很快,我们希望新增业务下游后也不需要重启。对于业务方来说,用户只关心业务逻辑,运维关心底层稳定性和 Job 执行效率。但是在实际处理中,一个大的困境在数据源。我们以 Kafka 为例,每多一个消费者就多一份网络消耗和数据反序列化的计算成本,对 Kafka 的压力就越大。我们应对的方法原理其实很简单,即基于源数据集来进行重构。

picture.image

相同 SLA 下的业务线,只要用了相同的 source,就可以把拓扑重构为新的模型。拓扑重构之后,用户侧无感知,SLA 也没有打破,但是效率确实成倍提升,而且对于上游 Kafka 的压力小了许多。

实时动态处理引擎整体架构

picture.image

我们希望这个引擎是一个会变形的引擎。上游用户可以通过 SQL、图形化/界面化配置,我们可以根据 schema 产生的 catalog 生成一个通用的自定义逻辑规则。之后用户还会对逻辑规则进行修改,比如进行校验或函数重构,我们再会转换成用户的物理规则(physical rule),我们现在是使用 Groovy 进行转换。转换成物理规则之后,还有其他一些问题要处理。

首先是动态化,包括:

  • UDF 动态化: 我们期望 UDF 改变也不用重启,所以 UDF 需要进行动态化编译。
  • 拓扑重构动态化: 重构之后拓扑改变,需要新的拓扑结构。
  • RPC 动态化: 可以加载动态的函数。

这些配置更新以后,经过 Planbuilder 生成 JobGraph,引擎再拉取配置。

这时也有一个问题:我们的规则非常多,不能因为一条规则的更改就更新所有规则。所以我们做的是增量更新,只对有需要的规则进行更新。

引擎拉取之后,会加载新的资源(RPC、Schema),并进行拓扑重构以及编译。因为之前给到的是一些 Groovy 的代码片段,用户可以将其热编译为物理规则。

此外我们还做了很多细致的工作,例如 Object catch。

举个例子:大部分埋点上报的是 String 格式的 Json数据,用户在进行数据清洗时就需要将 String 反序列化为 Json object,如果用户在规则中多次用到该 Json object 就会导致多次反序列化计算。因此,我们将反序列化后的 object 进行缓存,这样再次使用时就可以直接使用,避免重复反序列化成本。

picture.image 点击 阅读原文 ,了解 完整内容及PPT资料

  • End -

picture.image

100
0
0
0
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论