多条告白如次剧本只需引入一次
2021 年,字节扑腾旗下产物总 MAU 已胜过 19 亿。在以抖音、本日头条、无籽西瓜视频等为代办的产物交易后台下,宏大的引荐体例显得尤为要害。Flink 供给了特殊宏大的 SQL 模块和有状况计划模块。暂时在字节引荐场景,及时大略计数特性、窗口计数特性、序列特性仍旧实足迁徙到 Flink SQL 计划上。贯串 Flink SQL 和 Flink 有状况计划本领,咱们正在建立下一代通用的普通特性计划一致框架结构,憧憬不妨高效扶助常用有状况、无状况普通特性的消费。
交易后台
对至今日头条、抖音、无籽西瓜视频等字节扑腾旗下产物,鉴于 Feed 流和短实效的引荐是中心交易场景。而引荐体例最普通的燃料是特性,高效消费普通特性对交易引荐体例的迭代至关要害。
重要交易场景
抖音、火山短视频等为代办的短视频运用引荐场景,比方 Feed 流引荐、关心、应酬、同城等各个场景,完全在海内大约有 6 亿+范围 DAU;头条、无籽西瓜等为代办的 Feed 消息流引荐场景,比方 Feed 流、关心、子频段等各个场景,完全在海内数亿范围 DAU;交易痛点和挑拨
暂时字节扑腾引荐场景普通特性的消费近况是“百花齐放”。离线特性计划的基础形式都是经过耗费 Kafka、BMQ、Hive、HDFS、Abase、RPC 等数据源,鉴于 Spark、Flink 计划引擎实行特性的计划,尔后把特性的截止写入在线、离线保存。百般各别典型的普通特性计划散落在各别的效劳中,不足交易笼统,带来了较大的运维本钱和宁静性题目。
而更要害的是,不足一致的普通特性消费平台,使交易特性开拓迭代速率和保护生存诸多未便。如交易方需自行保护洪量离线工作、特性消费链路不足监察和控制、没辙满意连接兴盛的交易需要等。
在字节的交易范围下,建立一致的及时特性消费体例面对着较大挑拨,重要来自四个上面:
宏大的交易范围:抖音、头条、无籽西瓜、火山等产物的数据范围可到达每日平均 PB 级别。比方在抖音场景下,晚顶峰 Feed 播放量达数百万 QPS,存户端上报用户动作数据高达数万万 IOPS。交易方憧憬在任何功夫,特性工作都不妨做到连接流、耗费没有 lag 等,这就诉求特性消费完备特殊高的宁静性。
较高的特性及时化诉求:在以直播、电商、短视频为代办的引荐场景下,为保护引荐功效,及时特性离线消费的实效性需实行常态宁静于秒钟级别。
更好的扩充性和精巧性:跟着交易场景连接搀杂,特性需要更为精巧反复无常。从统计、序列、属性典型的特性消费,到须要精巧扶助窗口特性、多维特性等,交易方须要特性中台不妨扶助渐渐派生而来的新特性典型和需要。
交易迭代速率快:特性中台供给的面向交易的 DSL 须要充满场景,特性消费链路尽管让交易少写代码,底层的计划引擎、保存引擎对交易实足通明,完全开释交易计划、保存选型、调优的承担,完全实行及时普通特性的范围化消费,连接提高特性消费力;
迭代演进进程
在字节交易暴发式延长的进程中,为了满意形形色色的交易特性的需要,引荐场景派生出了稠密特性效劳。那些效劳在一定的交易场景和汗青前提下较好扶助了交易赶快兴盛,大概的过程如次:
引荐场景特性效劳演进过程
在这个中 2020 年头是一个要害节点,咱们发端在特性消费中引入 Flink SQL、Flink State 本领体制,渐渐在计数特性体例、模子演练的样品拼接、窗口特性等场景举行落地,探究出新一代特性消费计划的思绪。
新一代体例框架结构
贯串上述交易后台,咱们鉴于 Flink SQL 和 Flink 有状况计划本领从新安排了新一代及时特性计划计划。新计划的定位是:处置普通特性的计划和在线 Serving,供给越发笼统的普通特性交易层 DSL。在计划层,咱们鉴于 Flink SQL 精巧的数据处置表白本领,以及 Flink State 状况保存和计划本领等本领,扶助百般搀杂的窗口计划。极地面减少交易普通特性的消费周期,提高特性产出链路的宁静性。新的框架结构里,咱们将特性消费的链路分为数据源抽取/拼接、状况保存、计划三个阶段,Flink SQL 实行特性数据的抽取和流式拼接,Flink State 实行特性计划的中央状况保存。
有状况特性利害常要害的一类特性,个中最常用的即是带有百般窗口的特性,比方统计迩来 5 秒钟视频的播放 VV 等。对于窗口典型的特性在字节里面有少许鉴于保存引擎的计划,完全思绪是“轻离线重在线”,即把窗口状况保存、特性会合计划十足放在保存层和在线实行。离线数据流控制基础数据过滤和写入,离线明细数据依照功夫切分会合保存(一致于 micro batch),底层的保存大局部是 KV 保存、大概特意优化的保存引擎,在线层实行搀杂的窗口会合计划论理,每个乞求来了之后在线层拉取保存层的明细数据做会合计划。
咱们新的处置思绪是“轻在线重离线”,即把比拟重的功夫切片明细数据状况保存和窗口会合计划十足放在离线层。窗口截止会合经过离线窗口触发体制实行,把特性截止推到在线 KV 保存。在线模块特殊轻量级,只控制大略的在线 serving,极地面简化了在线层的框架结构搀杂度。在离线状况保存层。咱们重要依附 Flink 供给的原生状况保存引擎 RocksDB,充溢运用离线计划集群当地的 SSD 磁盘资源,极大减少在线 KV 保存的资源压力。
对于长窗口的特性(7 天之上窗口特性),因为波及 Flink 状况层明细数据的上溯进程,Flink Embedded 状况保存引擎没有供给更加好的外部数据回灌体制(大概说不符合做)。所以对于这种“状况冷启用”场景,咱们引入了重心化保存动作底层状况保存层的保存介质,完全是 Hybrid 框架结构。比方 7 天以内的状况保存在当地 SSD,7~30 天状况保存到重心化的保存引擎,离线数据上溯不妨特殊简单的写入重心化保存。
除窗口特性外,这套体制同样实用于其余典型的有状况特性(如序列典型的特性)。
及时特性分门别类体制
特性典型
设置
特性举例
有状况特性
有状况特性是一类特殊要害的特性,咱们对有状况特性的设置是:计划特性须要缓存左右文数据。
带有窗口的特性,比方抖音视频迩来1h的点赞量(滑行窗口)、直播间用户迩来一个 session 的看播时间长度(session 窗口)等;序列特性,比方迩来100个引荐展示视频。无状况特性
大略的 ETL 特性,经过大略的数据过滤不妨计划的特性。
模子预估特性
须要过程外部搀杂模子预估的特性
用户的年纪、性别等特性。
图特性
在直播和应酬联系场景生存比拟多的须要二跳联系的图典型的特性。
很多图特性同声也是有状况典型的特性。
礼品排序:用户观察最多的主播收到最多的礼品,首要选择须要找到用户观察最多的主播 ArchorId,而后经过 archon_id 获得到主播收到最多的礼品 id;应酬联系:心腹(大概是发掘出来的联系)关心、看播、送人情、连麦的屋子,应酬联系自然是图数据构造。完全框架结构
数据源层
在新的一体化特性框架结构中,咱们一致把百般典型数据源笼统为 Schema Table,这是由于底层依附的 Flink SQL 计划引擎层对数据源供给了特殊和睦的 Table Format 笼统。在引荐场景,依附的数据源特殊百般,每个特性上流依附一个大概多个数据源。数据源不妨是 Kafka、RMQ、KV 保存、RPC 效劳。对于多个数据源,扶助数据泉源式、批式拼接,拼接典型囊括 Window Join 和鉴于 key 粒度的 Window Union Join,维表 Join 扶助 Abase、RPC、HIVE 等。简直每种典型的拼接论理如次:
数据源典型
Schema 领会
Kafka、BMQ
Kafka、BMQ 等 message 典型基础都是 JSON 和 PB,是自刻画的数据典型。不妨特殊简单地映照成 SchemaTable 方法,个中对于 PB 典型,交易须要上传 PB IDL 实行 Table Schema 设置。
KV保存
KV 保存里的 Value 大局部为 JSON、PB 方法,和 MQ 一致。交易方经过供给 PB IDL 实行 Table Schema 设置。咱们经过 FlinkSQL 的维表 Join 本领,把普遍的获得外部保存数据源进程笼统为基础的维表 Join 操纵,简化交易开拓周期。
RPC
FlinkSQL 供给了对 RPC 维表的 Join 本领,交易供给 RPC Thrift IDL 完备 rpc response Table Schema 设置。经过维表 Join,咱们把普遍的经过 RPC 获得外部数据源的进程笼统为了基础维表 Join 模子,简化交易开拓周期。
Hive
Hive 自己即是 SchemaTable 的保存方法,对于在线 Join 数据量较小的离线 Hive 数据(本来即是 MapSide Join),可经过 Hive 维表 Join 实行。
三种典型的 Join 和 Union 不妨拉拢运用,实行搀杂的普遍据流拼接。比方(A union B) Window Join (C Lookup Join D)。
拼接典型
拼接论理
备注
Window Join
运用 Flink 原生 API 供给的 Join 算子,把多个数据流浪入相同学口的数据 Join 起来。
径直在原始数据流上运用 TumblingWindow 举行切分,按照event_time 或 process_time 对齐两个窗口后再关系数据。
鉴于 Key 粒度的 Interval State Join
和样品拼接论理一致。经过 Union 上流多个数据源,在每个关系主键上头备案 timer,等候一个恒定的功夫窗口实行普遍据源的 Join 操纵。
Interval State Join 是运用 State 保存数据再处置。上流两个数据流过程 Union 后,同一个 uid 的 instance 数据和 label 数据落在同一个 operator 内,Joiner 中正负例样品的爆发即是经过这种 Join 办法。
Lookup 维表 Join
经过关系主键,从 Abase、RPC、Hive 等效劳察看须要关系的数据,实行数据的 Join 操纵。
普遍据源 Union
普遍据源 Union 起来
其余,Flink SQL 扶助搀杂字段的计划本领,也即是交易方不妨鉴于数据源设置的 TableSchema 普通字段实行扩充字段的计划。交易计划论理实质是一个 UDF,咱们会供给 UDF API 接口给交易方,而后上传 JAR 到特性后盾加载。其余对于比拟大略的计划论理,后盾也扶助经过提交大略的 Python 代码实行多谈话计划。
交易 DSL
从交易视角供给莫大笼统的特性消费 DSL 谈话,樊篱底层计划、保存引擎详细,让交易方聚焦于交易特性设置。交易 DSL 层供给:数据根源、数据方法、数据抽取论理、数据天生特性典型、数据输入办法等。
状况保存层
如下文所述,新的特性一体化计划处置的重要痛点是:怎样应付百般典型(普遍是滑行窗口)有状况特性的计划题目。对于这类特性,在离线计划层框架结构里会有一个状况保存层,把抽取层索取的 RawFeature 依照切片 Slot 保存起来(切片不妨是功夫切片、也不妨是 Session 切片等)。切片典型在里面是一个接口典型,在框架结构上不妨按照交易需要自行扩充。状况内里本来保存的不是原始 RawFeature(保存原始的动作数据太滥用保存空间),而是变化为 FeaturePayload 的一种 POJO 构造,这个构造内里扶助了罕见的百般数据构造典型:
Int:保存大略的计数值典型(多维度 counter);HashMap:保存二维计数值,比方 Action Counter,key 为 target_id,value 为计数值;SortedMap: 保存 topk 二维计数 ;LinkedList: 保存 id_list 典型数据;HashMap>:保存二维 id_list;自设置典型,交易不妨按照需要 FeaturePayload 内里自设置数据典型状况层革新的交易接口:输出是 SQL 抽取/拼接层抽掏出来的 RawFeature,交易方不妨按照交易需务实现 updateFeatureInfo 接口对状况层的革新。对于常用的特性典型内置实行了 update 接口,交易方自设置特性典型不妨接受 update 接话柄现。
/** * 特性状况update接口 */public interface FeatureStateApi extends Serializable { /** * 特性革新接口, 上流每条日记会索取需要字段变换为fields, 用来革新对应的特性状况 * * @param fields * context: 生存特性称呼、主键 和 少许摆设参数; * oldFeature: 特性之前的状况 * fields: 平台/摆设文献 中的抽取字段 * @return */FeaturePayLoad assign(Context context,FeaturePayLoad feature, Map<String, Object> rawFeature);}复制代码
固然对于无状况的 ETL 特性是不须要状况保存层的。
计划层
特性计划层实行特性计划会合论理,有状况特性计划输出的数据是状况保存层保存的带有切片的 FeaturePayload 东西。大略的 ETL 特性没有状况保存层,输出径直是 SQL 抽取层的数据 RawFeature 东西,简直的接口如次:
/** * 有状况特性计划接口 */public interface FeatureStateApi extends Serializable { /** * 特性会合接口,会按照摆设的特性计划窗口, 读取窗口内一切特性状况,排序后传入该接口 * * @param featureInfos, 包括2个field * timeslot: 特性状况对应的功夫槽 * Feature: 该功夫槽的特性状况 * @return */ FeaturePayLoad aggregate(Context context, List<Tuple2<Slot, FeaturePayLoad>> slotStates);}复制代码
有状况特性会合接口
/** * 无状况特性计划接口 */public interface FeatureConvertApi extends Serializable { /** * 变换接口, 上流每条日记会索取需要字段变换为fields, 无状况计划时,变换为里面的feature典型; * * @param fields * fields: 平台/摆设文献 中的抽取字段 * @return */ FeaturePayLoad convert(Context context, FeaturePayLoad featureSnapshot, Map<String, Object> rawFeatures);}复制代码
无状况特性计划接口
其余经过触发体制来触发特性计划层的实行,暂时扶助的触发体制重要有:
战略
证明
OnTimerTrigger
周期性准时触发特性的计划论理
OnUpdateTrigger
上流状况层历次革新即触发特性计划
CustomTrigger
自设置特性计划的触发机会
交易落地
暂时在字节引荐场景,新一代特性框架结构仍旧在抖音直播、电商、推送、抖音引荐等场景连接上线了少许及时特性。主假如有状况典型的特性,带有窗口的一维统计典型、二维倒排拉锁典型、二维 TOPK 典型、及时 CTR/CVR Rate 典型特性、序列典型特性等。
在交易中心目标完毕上面功效明显。在直播场景,依靠新特性框架结构宏大的表白本领上线了一批特性之后,交易看播中心目标、互动目标收益特殊明显。在电阛阓景,鉴于新特性框架结构上线了 400+及时特性。个中在直播电商上面,交易中心 GMV、下单率目标收益明显。在抖音推送场景,鉴于新特性框架结构离线状况的保存本领,会合用户动作数据而后写入卑劣各路保存,极地面缓和了交易卑劣数据库的压力,在少许场景中 QPS 不妨低沉到之前的 10%安排。其余,抖音引荐 Feed、指摘等交易都在鉴于新特性框架结构重构原有的特性体制。
犯得着一提的是,在电商和抖音直播场景,Flink 流式工作状况最大仍旧到达 60T,并且这个量级还在连接增大。估计不久的未来,单工作的状况有大概会冲破 100T,这对框架结构的宁静性是一个不小的挑拨。
本能优化
Flink State Cache
暂时 Flink 供给两类 StateBackend:鉴于 Heap 的 FileSystemStateBackend 和鉴于 RocksDB 的 RocksDBStateBackend。对于 FileSystemStateBackend,因为数据都在外存中,考察速度很快,没有特殊开支。而 RocksDBStateBackend 生存查盘、序列化/反序列化等特殊开支,CPU 运用量会有鲜明飞腾。在字节里面有洪量运用 State 的功课,对于大状况功课,常常会运用 RocksDBStateBackend 来处置当地状况数据。RocksDB 是一个 KV 数据库,以 LSM 的情势构造数据,在本质运用的进程中,有以次特性:
运用层和 RocksDB 的数据交互是以 Bytes 数组的情势举行,运用层历次考察都须要序列化/反序列化;数据以追加的情势连接写入 RocksDB 中,RocksDB 后盾会连接举行 compaction 来简略失效数据。交易方运用 State 的场景多是 get-update,在运用 RocksDB 动作当地状况保存的进程中,展示过以次题目:
爬虫数据引导热 key,状况会连接举行革新(get-update),单 KV 数据到达 5MB,而 RocksDB 追加革新的特性引导后盾在连接举行 flush 和 compaction,单 task 展示慢节点(抖音直播场景)。电阛阓景功课普遍为大状况功课(暂时已上线功课状况约 60TB),交易论理中会一再举行 State 操纵。在融洽 Flink State 进程中创造 CPU 的开支和原有的鉴于外存或 abase 的实行有 40%~80%的升高。经优化后,CPU 开支重要会合在序列化/反序列化的进程中。对准上述题目,不妨经过在外存保护一个东西 Cache,到达优化热门数据考察和贬低 CPU 开支的手段。经过上述后台引见,咱们蓄意能为 StateBackend 供给一个通用的 Cache 功效,经过 Flink StateBackend Cache 功效安排计划完毕以次目的:
缩小 CPU 开支:经过对热门数据举行缓存,缩小和底层 StateBackend 的交互度数,到达缩小序列化/反序列化开支的手段。提高 State 含糊本领:经过减少 Cache 后,State 含糊本领应比原有的 StateBackend 供给的含糊本领更高。表面上在 Cache 充满大的情景下,含糊本领应和鉴于 Heap 的 StateBackend 好像。Cache 功效通用化:各别的 StateBackend 不妨径直适配该 Cache 功效。暂时咱们重要扶助 RocksDB,将来蓄意不妨径直供给给其余 StateBackend 运用,比方 RemoteStateBackend。过程和字节普通框架结构 Flink 共青团和少先队的协作,在及时特性消费晋级,上线 Cache 大局部场景的 CPU 运用率大约会有高达 50%安排的收益;
PB IDL 裁剪
在字节里面的及时特性离线天生链路傍边,咱们重要依附的数据流是 Kafka。那些 Kafka 都是经过 PB 设置的数据,字段稠密。公司级其余大 Topic 普遍会有 100+的字段,但大局部的特性消费工作只运用了个中的局部字段。对于 Protobuf 方法的数据源,咱们不妨实足经过裁剪数据流,mask 少许非需要的字段来俭朴反序列化的开支。PB 典型的日记,不妨径直裁剪 idl,维持需要字段的序号静止,在反序列化的功夫会跳过 unknown field 的领会,这对于 CPU 来说是更俭朴的,然而搜集带宽不会有收益,估计裁剪后能俭朴特殊多的 CPU 资源。在上线了 PB IDL 裁剪之后,大局部工作的 CPU 收益在 30%安排。
遇到的题目
新框架结构特性消费工作实质即是一个有状况的 Flink 工作,底层的状况保存 StateBackend 主假如当地的 RocksDB。重要面对两个比拟难解的题目,一是工作 DAG 变革 Checkpoint 作废,二是当地保存不许很好地扶助特性状况汗青数据上溯。
及时特性工作不许动静增添新的特性:对于一个线上的 Flink 及时特性消费工作,咱们不许随便增添新的特性。这是因为引入新的特性会引导 Flink 工作计划的 DAG 爆发变换,进而引导 Flink 工作的 Checkpoint 没辙回复,这对及时有状况特性消费工作来说是不许接收的。暂时咱们的解法是遏止变动线上安置的特性工作摆设,但这也就引导了线上天生的特性是不许随意底线的。对于这个题目姑且没有找到更好的处置方法,后期仍需连接探究。特性状况冷启用题目:暂时重要的状况保存引擎是 RocksDB,不许很好地扶助状况数据的上溯。后续筹备
暂时新一代框架结构还在字节引荐场景中赶快演进,暂时已较好处置了及时窗口特性的消费题目。
出于实行一致引荐场景下特性消费的手段,咱们后续会连接鉴于 Flink SQL 流批一体本领,在批式特性消费发力。其余也会鉴于 Hudi 数据湖本领,实行特性的及时入湖,高效扶助模子演练场景离线特性上溯痛点。准则引擎目标,安置连接探究 CEP,激动在电阛阓景有更多落地试验。在及时窗口计划目标,将连接深刻调查研究 Flink 原生窗口体制,以期处置暂时计划面对的窗口特性数据出场题目。
扶助批式特性:这套特性消费计划主假如处置及时有状况特性的题目,而暂时字节离线场景下再有洪量批式特性是经过 Spark SQL 工作消费的。后续咱们也会鉴于 Flink SQL 流批一体的计划本领,供给对批式场景特性的一致扶助,暂时也发端有了几个场景的落地;特性离线入湖:鉴于 Hudi On Flink 扶助及时特性的离线数仓树立,主假如为了扶助模子演练样品拼接场景离线特性上溯;Flink CEP 准则引擎扶助:Flink SQL 实质上即是一种准则引擎,暂时在线上咱们把 Flink SQL 动作交易 DSL 过滤语义底层的实行引擎。但 Flink SQL 长于表白的 ETL 典型的过滤准则,不许表白带偶尔序典型的准则语义。在直播、电阛阓景的时序准则须要试验 Flink CEP 越发搀杂的准则引擎。Flink Native Windowing 体制引入:对于窗口典型的有状况特性,咱们暂时沿用下文所述的笼统 SlotState 功夫切片计划一致举行扶助。其余 Flink 自己供给了特殊完备的窗口体制,经过 Window Assigner、Window Trigger 等组件不妨特殊精巧地扶助百般窗书面语义。所以后续咱们也会在窗口特性计划场景引入 Flink 原生的 Windowing 体制,越发精巧地扶助窗口特性迭代。Flink HybridState Backend 框架结构:暂时在字节的线上场景中,Flink 底层的 StateBackend 默许都是运用 RocksDB 保存引擎。这种内嵌的保存引擎不许经过外部体制去供给状况数据的回灌和多工作共享,所以咱们须要扶助 KV 重心化保存计划,实行精巧的特性状况上溯。静态属性典型特性一致处置:经过特性平台供给一致的 DSL 语义,一致处置其余外部静态典型的特性效劳。比方少许其余交易共青团和少先队维度的用户分门别类、标签效劳等。