节跳动埋点数据流建设与治理实践(上)
bigegpt 2024-10-27 08:22 6 浏览
本文将介绍字节跳动在埋点数据流业务场景遇到的需求和挑战以及具体实践,分为上下篇呈现。上篇主要包含埋点数据流简介与埋点数据流建设实践;下篇主要包含埋点数据流治理实践以及未来规划。
埋点数据流
埋点数据流在字节跳动
埋点数据流主要处理的数据是埋点,埋点也叫Event Tracking,是数据和业务之间的桥梁,也是数据分析、推荐、运营的基石。
用户在使用 App 、小程序、 Web 等各种线上应用时产生的用户行为数据主要通过埋点的形式进行采集上报,按不同的来源可以分为:
- 客户端埋点
- Web端埋点
- 服务端埋点
埋点通过埋点收集服务接收到MQ,经过一系列的Flink实时ETL对埋点进行数据标准化、数据清洗、数据字段扩充、实时风控反作弊等处理,最终分发到不同的下游。下游主要包括推荐、广告、ABTest、行为分析系统、实时数仓、离线数仓等。因为埋点数据流处在整个数据处理链路的最上游,所以决定了“稳定性”是埋点数据流最为关注的一点。
字节跳动的埋点数据流规模
字节跳动埋点数据流的规模比较大,体现在以下几个方面:
- 接入的业务数量很多,包括抖音、今日头条、西瓜视频、番茄小说在内的多个App和服务,都接入了埋点数据流。
- 流量很大,当前字节跳动埋点数据流峰值流量超过1亿每秒,每天处理超过万亿量级埋点,PB级数据存储增量。
- ETL任务规模体量较大,在多个机房部署了超过1000个Flink任务和超过1000个MQ Topic,使用了超过50万Core CPU资源,单个任务最大超过12万Core CPU,单个MQ Topic最大达到10000个partition。
那么在这么巨大的流量和任务规模下,埋点数据流主要处理的是哪些问题呢?我们来看几个具体的业务场景。
业务场景
- UserAction ETL
在推荐场景中,由于埋点种类多、流量巨大,而推荐只关注其中部分埋点,因此需要通过UserAction ETL对埋点流进行处理,对这个场景来说有两个需求点:
- 数据流的时效性
- ETL规则动态更新
为了提升下流推荐系统的处理效率,我们在数据流配置ETL规则对推荐关注的埋点进行过滤,并对字段进行删减、映射、标准化等清洗处理,将埋点打上不同的动作类型标识,处理之后的埋点内部一般称为UserAction。UserAction与服务端展现、Feature等数据会在推荐Joiner任务的分钟级窗口中进行拼接处理,产出instance训练样本。
举个例子:一个客户端的文章点赞埋点,描述了一个用户在某一个时间点对某一篇文章进行了点赞操作,这个埋点经过埋点收集服务进入ETL链路,通过UserAction ETL处理后,实时地进入推荐Joiner任务中拼接生成样本,更新推荐模型,从而提升用户的使用体验。
如果产出UserAction数据的ETL链路出现比较大的延迟,就不能在拼接窗口内及时地完成训练样本的拼接,可能会导致用户体验的下降,因此对于推荐来说,数据流的时效性是比较强的需求。而推荐模型的迭代和产品埋点的变动都可能导致UserAction ETL规则的变动,如果我们把这个ETL规则硬编码在代码中,每次修改都需要升级代码并重启相关的Flink ETL任务,这样会影响数据流的稳定性和数据的时效性,因此这个场景的另一个需求是ETL规则的动态更新。
- 数据分流
抖音的埋点Topic晚高峰超过一亿每秒,而下游电商、直播、短视频等不同业务关注的埋点都只是其中一部分。如果每个业务都分别使用一个Flink任务去消费抖音的全量埋点去过滤出自己关注的埋点,会消耗大量的计算资源,同时也会造成MQ集群带宽扇出非常严重,影响MQ集群的稳定性。
因此我们提供了数据分流服务,实现上是我们使用一个Flink任务去消费上游埋点Topic,通过在任务中配置分流规则的方式,将各个业务关注的埋点分流到下游的小Topic中提供给各业务消费,减少不必要的资源开销,同时也降低了MQ集群出带宽。
分流需求大多对SLA有一定要求,断流和数据延迟可能会影响下流的推荐效果、广告收入以及数据报表更新等。另外随着业务的发展,实时数据需求日益增加,分流规则新增和修改变得非常频繁,如果每次规则变动都需要修改代码和重启任务会对下游造成较大影响,因此在数据分流这个场景,规则的动态更新也是比较强的需求。
- 容灾降级
另一个场景是容灾降级。数据流容灾首先考虑的是防止单个机房级别的故障导致埋点数据流完全不可用,因此埋点数据流需要支持多机房的容灾部署。其次当出现机房级别的故障时,需要将故障机房的流量快速调度到可用机房实现服务的容灾恢复,因此需要埋点数据流具备机房间快速切流的能力。
而数据流降级主要考虑的是埋点数据流容量不足以承载全部流量的场景,比如春晚活动、电商大促这类有较大突发流量的场景。为了保障链路的稳定性和可用性,需要服务具备主动或者被动的降级能力。
埋点数据流遇到挑战
挑战主要是流量大和业务多导致的。流量大服务规模就大,不仅会导致成本治理的问题,还会带来单机故障多、性能瓶颈等因素引发的稳定性问题。而下游业务多、需求变化频繁,推荐、广告、实时数仓等下游业务对稳定性和实时性都有比较高的要求。
在流量大、业务多这样的背景下,如何保障埋点数据流稳定性的同时降低成本、提高效率,是埋点数据流稳定性治理和成本治理面对的挑战。
埋点数据流建设实践
上文我们了解了埋点数据流的业务场景和面对的挑战,接下来会介绍埋点数据流在ETL链路建设和容灾与降级能力上的一些实践。
ETL链路建设
- 发展历程
埋点数据流ETL链路发展到现在主要经历了三个阶段。
第一个阶段是2018年以前,业务需求快速迭代的早期阶段。那时我们主要使用PyJStorm与基于Python的规则引擎构建主要的流式处理链路。特点是比较灵活,可以快速支持业务的各种需求,伴随着埋点量的快速上涨,PyJStorm暴露出很多稳定性和运维上的问题,性能也不足以支撑业务增长。2018年内部开始大力推广Flink,并且针对大量旧任务使用PyJStorm的情况提供了PyJStorm到PyFlink的兼容适配,流式任务托管平台的建设一定程度上也解决了流式任务运维管理问题,数据流ETL链路也在2018年全面迁移到了PyFlink,进入到Flink流式计算的新时代。
第二个阶段是2018年到2020年,随着流量的进一步上涨,PyFlink和kafka的性能瓶颈以及当时使用的JSON数据格式带来的性能和数据质量问题纷纷显现出来。与此同时,下流业务对数据延迟、数据质量的敏感程度与日俱增。我们不仅对一些痛点进行了针对性优化,还花费一年多的时间将整个ETL链路从PyFlink切换到Java Flink,使用基于Groovy的规则引擎替换了基于Python的规则引擎,使用Protobuf替代了JSON,新链路相比旧链路性能提升了数倍。同时大数据开发平台和流量平台的建设提升了埋点数据流在任务开发、ETL规则管理、埋点管理、多机房容灾降级等多方面的能力。
第三个阶段是从2021年开始至今,进一步提升数据流ETL链路的性能和稳定性,在满足流量增长和需求增长的同时,降低资源成本和运维成本是这一阶段的主要目标。我们主要从三个方面进行了优化。
- 优化了引擎性能,随着流量和ETL规则的不断增加,我们基于Groovy的规则引擎使用的资源也在不断增加,所以基于Janino对规则引擎进行了重构,引擎的性能得到了十倍的提升。
- 基于流量平台建设了一套比较完善的埋点治理体系,通过埋点下线、埋点管控、埋点采样等手段降低埋点成本。
- 将链路进行了分级,不同的等级的链路保障不同的SLA,在资源不足的情况下,优先保障高优链路。
接下来是我们2018至2020年之间埋点数据流ETL链路建设的一些具体实践。
- 基于规则引擎的Flink ETL
在介绍业务场景时,提到我们一个主要的需求是ETL规则的动态更新,那么我们来看一下埋点数据流Flink ETL 任务是如何基于规则引擎支持动态更新的,如何在不重启任务的情况下,实时的更新上下游的Schema信息、规则的处理逻辑以及修改路由拓扑。
首先,我们在流量平台上配置了上下游数据集的拓扑关系、Schema和ETL规则,然后通过ConfigCenter将这些元数据发送给Flink ETL Job,每个Flink ETL Job的TaskManager都有一个Meta Updater更新线程,更新线程每分钟通过RPC请求从流量平台拉取并更新相关的元数据,Source operator从MQ Topic中消费到的数据传入ProcessFunction,根据MQ Topic对应的Schema信息反序列化为InputMessage,然后进入到规则引擎中,通过规则索引算法匹配出需要运行的规则,每条规则我们抽象为一个Filter模块和一个Action模块,Fliter和Action都支持UDF,Filter筛选命中后,会通过Action模块对数据进行字段的映射和清洗,然后输出到OutputMessage中,每条规则也指定了对应的下游数据集,路由信息也会一并写出。
当OutputMessage输出到Slink后,Slink根据其中的路由信息将数据发送到SlinkManager管理的不同的Client中,然后由对应的Client发送到下游的MQ中。
- 规则引擎
规则引擎为埋点数据流ETL链路提供了动态更新规则的能力,而埋点数据流Flink ETL Job使用的规则引擎也经历了从Python到Groovy再到Janino的迭代。
由于Python脚本语言本身的灵活性,基于Python实现动态加载规则比较简单。通过Compile函数可以将一段代码片段编译成字节代码,再通过eval函数进行调用就可以实现。但Python规则引擎存在性能较弱、规则缺乏管理等问题。
迁移到Java Flink后,在流量平台上统一管理运维ETL规则以及schema、数据集等元数据,用户在流量平台编辑相应的ETL规则,从前端发送到后端,经过一系列的校验最终保存为逻辑规则。引擎会将这个逻辑规则编译为实际执行的物理规则,基于Groovy的引擎通过GroovyClassLoader动态加载规则和对应的UDF。虽然Groovy引擎性能比Python引擎提升了多倍,但Groovy本身也存在额外的性能开销,因此我们又借助Janino可以动态高效地编译Java代码直接执行的能力,将Groovy替换成了Janino,同时也将处理Protobuf数据时使用的DynamicMessage替换成了GeneratedMessage,整体性能提升了10倍。
除了规则引擎的迭代,我们在平台侧的测试发布和监控方面也做了很多建设。测试发布环节支持了规则的线下测试,线上调试,以及灰度发布的功能。监控环节支持了字段、规则、任务等不同粒度的异常监控,如规则的流量波动报警、任务的资源报警等。
- Flink拆分任务
规则引擎的应用解决了埋点数据流ETL链路如何快速响应业务需求的问题,实现了ETL规则的动态更新,从而修改ETL规则不需要修改代码和重启任务。
但规则引擎本身的迭代、流量增长导致的资源扩容等场景,还是需要升级重启Flink任务,导致下游断流。
除了重启断流外,大任务还可能在重启时遇到启动慢、队列资源不足或者资源碎片导致起不来等情况。
针对这些痛点我们上线了Flink拆分任务,本质上是将一个大任务拆分为一组子任务,每个子任务按比例去消费上游Topic的部分Partition,按相同的逻辑处理后再分别写出到下游Topic。
举个例子:上游Topic有200个Partition,我们在一站式开发平台上去配置Flink拆分任务时只需要指定每个子任务的流量比例,每个子任务就能自动计算出它需要消费的topic partition区间,其余参数也支持按流量比例自动调整。
拆分任务的应用使得数据流除了规则粒度的灰度发布能力之外,还具备了Job粒度的灰度发布能力,升级扩容的时候不会发生断流,上线的风险更可控。同时由于拆分任务的各子任务是独立的,因此单个子任务出现反压、Failover对下游的影响更小。另一个优点是,单个子任务的资源使用量更小,资源可以同时在多个队列进行灵活的部署。
容灾与降级能力建设
说到ETL链路建设,埋点数据流在容灾与降级能力建设方面也进行了一些实践。
首先是容灾能力的建设,埋点数据流在Flink、MQ、Yarn、HDFS等组件支持多机房容灾的基础上完成了多机房容灾部署,并准备了多种流量调度的预案。
正常情况下流量会均匀打到多个机房,MQ在多个机房间同步,Flink ETL Job默认从本地MQ进行消费,如果某个机房出现故障,我们根据情况可以选择通过配置下发的方式从客户端将流量调度到其他非受灾机房,也可以在CDN侧将流量调度到其他非受灾机房。埋点数据流ETL链路可以分钟级地进入容灾模式,迅速将故障机房的Flink Job切换到可用的机房。
其次是服务降级能力的建设,主要包含服务端降级策略和客户端降级策略。服务端降级策略主要通过LB限流、客户端进行退避重试的机制来实现,客户端降级策略通过配置下发可以降低埋点的上报频率。
举个例子:在春晚活动中参与的用户很多,口播期间更是有着非常巨大的流量洪峰,2021年春晚活动期间为了应对口播期间的流量洪峰,埋点数据流开启了客户端的降级策略,动态降低了一定比例用户的埋点上报频率,在口播期间不上报,口播结束后迅速恢复上报。在降级场景下,下游的指标计算是通过消费未降级用户上报的埋点去估算整体指标。目前我们在此基础上进行了优化,客户端目前的降级策略可以更近一步的根据埋点的分级信息去保障高优的埋点不降级,这样可以在活动场景下保障活动相关的埋点不降级的上报,支持下游指标的准确计算。
下篇主要包含埋点数据流治理实践以及未来规划。
作者:石伟 字节跳动数据平台开发套件团队
相关推荐
- AI「自我复制」能力曝光,RepliBench警示:大模型正在学会伪造身份
-
科幻中AI自我复制失控场景,正成为现实世界严肃的研究课题。英国AISI推出RepliBench基准,分解并评估AI自主复制所需的四大核心能力。测试显示,当前AI尚不具备完全自主复制能力,但在获取资源...
- 【Python第三方库安装】介绍8种情况,这里最全看这里就够了!
-
**本图文作品主要解决CMD或pycharm终端下载安装第三方库可能出错的问题**本作品介绍了8种安装方法,这里最全的python第三方库安装教程,简单易上手,满满干货!希望大家能愉快地写代码,而不要...
- pyvips,一个神奇的 Python 库!(pythonvip视频)
-
大家好,今天为大家分享一个神奇的Python库-pyvips。在图像处理领域,高效和快速的图像处理工具对于开发者来说至关重要。pyvips是一个强大的Python库,基于libvips...
- mac 安装tesseract、pytesseract以及简单使用
-
一.tesseract-OCR的介绍1.tesseract-OCR是一个开源的OCR引擎,能识别100多种语言,专门用于对图片文字进行识别,并获取文本。但是它的缺点是对手写的识别能力比较差。2.用te...
- 实测o3/o4-mini:3分钟解决欧拉问题,OpenAI最强模型名副其实!
-
号称“OpenAI迄今为止最强模型”,o3/o4-mini真实能力究竟如何?就在发布后的几小时内,网友们的第一波实测已新鲜出炉。最强推理模型o3,即使遇上首位全职提示词工程师RileyGoodsid...
- 使用Python将图片转换为字符画并保存到文件
-
字符画(ASCIIArt)是将图片转换为由字符组成的艺术作品。利用Python,我们可以轻松实现图片转字符画的功能。本教程将带你一步步实现这个功能,并详细解释每一步的代码和实现原理。环境准备首先,你...
- 5分钟-python包管理器pip安装(python pip安装包)
-
pip是一个现代的,通用、普遍的Python包管理工具。提供了对Python包的查找、下载、安装、卸载的功能,是Python开发的基础。第一步:PC端打开网址:选择gz后缀的文件下载第二步:...
- 网络问题快速排查,你也能当好自己家的网络攻城狮
-
前面写了一篇关于网络基础和常见故障排查的,只列举了工具。没具体排查方式。这篇重点把几个常用工具的组合讲解一下。先有请今天的主角:nslookup及dig,traceroute,httping,teln...
- 终于把TCP/IP 协议讲的明明白白了,再也不怕被问三次握手了
-
文:涤生_Woo下周就开始和大家成体系的讲hadoop了,里面的每一个模块的技术细节我都会涉及到,希望大家会喜欢。当然了你也可以评论或者留言自己喜欢的技术,还是那句话,希望咱们一起进步。今天周五,讲讲...
- 记一次工控触摸屏故障的处理(工控触摸屏维修)
-
先说明一下,虽然我是自动化专业毕业,但已经很多年不从事现场一线的工控工作了。但自己在单位做的工作也牵涉到信息化与自动化的整合,所以平时也略有关注。上一周一个朋友接到一个活,一家光伏企业用于启动机组的触...
- 19、90秒快速“读懂”路由、交换命令行基础
-
命令行视图VRP分层的命令结构定义了很多命令行视图,每条命令只能在特定的视图中执行。本例介绍了常见的命令行视图。每个命令都注册在一个或多个命令视图下,用户只有先进入这个命令所在的视图,才能运行相应的命...
- 摄像头没图像的几个检查方法(摄像头没图像怎么修复)
-
背景描述:安防监控项目上,用户的摄像头运行了一段时间有部分摄像头不能进行预览,需要针对不能预览的摄像头进行排查,下面列出几个常见的排查方法。问题解决:一般情况为网络、供电、设备配置等情况。一,网络检查...
- 小谈:必需脂肪酸(必需脂肪酸主要包括)
-
必需脂肪酸是指机体生命活动必不可少,但机体自身又不能合成,必需由食物供给的多不饱和脂肪酸(PUFA)。必需脂肪酸主要包括两种,一种是ω-3系列的α-亚麻酸(18:3),一种是ω-6系列的亚油酸(18:...
- 期刊推荐:15本sci四区易发表的机械类期刊
-
虽然,Sci四区期刊相比收录在sci一区、二区、三区的期刊来说要求不是那么高,投稿起来也相对容易一些。但,sci四区所收录的期刊中每本期刊的投稿难易程度也是不一样的。为方便大家投稿,本文给大家推荐...
- be sick of 用法考察(be in lack of的用法)
-
besick表示病了,做谓语.本身是形容词,有多种意思.最通常的是:生病,恶心,呕吐,不适,晕,厌烦,无法忍受asickchild生病的孩子Hermother'sverysi...
- 一周热门
- 最近发表
-
- AI「自我复制」能力曝光,RepliBench警示:大模型正在学会伪造身份
- 【Python第三方库安装】介绍8种情况,这里最全看这里就够了!
- pyvips,一个神奇的 Python 库!(pythonvip视频)
- mac 安装tesseract、pytesseract以及简单使用
- 实测o3/o4-mini:3分钟解决欧拉问题,OpenAI最强模型名副其实!
- 使用Python将图片转换为字符画并保存到文件
- 5分钟-python包管理器pip安装(python pip安装包)
- 网络问题快速排查,你也能当好自己家的网络攻城狮
- 终于把TCP/IP 协议讲的明明白白了,再也不怕被问三次握手了
- 记一次工控触摸屏故障的处理(工控触摸屏维修)
- 标签列表
-
- mybatiscollection (79)
- mqtt服务器 (88)
- keyerror (78)
- c#map (65)
- resize函数 (64)
- xftp6 (83)
- bt搜索 (75)
- c#var (76)
- mybatis大于等于 (64)
- xcode-select (66)
- mysql授权 (74)
- 下载测试 (70)
- linuxlink (65)
- pythonwget (67)
- androidinclude (65)
- logstashinput (65)
- hadoop端口 (65)
- vue阻止冒泡 (67)
- oracle时间戳转换日期 (64)
- jquery跨域 (68)
- php写入文件 (73)
- kafkatools (66)
- mysql导出数据库 (66)
- jquery鼠标移入移出 (71)
- 取小数点后两位的函数 (73)