合作机构:阿里云 / 腾讯云 / 亚马逊云 / DreamHost / NameSilo / INWX / GODADDY / 百度统计
首先简要介绍一下 B 站标签系统的演进历程。
B 站标签系统建立于 2021 年初。当时立项的背景为,业务侧人均取数的需求越来越多,希望能够加速数据取用的效率,标签系统内部立项建设启动。
在最初的版本中形成了基础的标签圈群的能力,以开放 API 的方式对外提供服务,基本上能够满足当时的业务需求。
随着越来越多的标签接入需求,以及业务侧越来越高的人群圈选频率,系统逐步面临各种问题:
针对 2021 系统上线后面临的问题进行点状优化,并通过平台化的方式对接更多业务场景。
更加系统化地建设标签系统,在业务侧更好地打通数据平台和业务应用:
系统整体架构从下到上可以分为三个层级:依次为标签生产、人群圈选和人群应用。
数据流转链路是整个标签系统整体架构的核心,标签系统的主要作用是把各种类型的原始数据快速生产成人群,最终对接业务侧各种场景的使用。
业务数据,包括 DB 数据,以及日志和埋点上报等数据。
一方面,业务数据通过大数据的数据集成能力入仓得到 Hive 表和 Iceberg 表,再通过标签构建,出仓进入到 ClickHouse。这是离线的链路。
另一方面,移动端的埋点数据也是依托大数据的能力,会直接进入到ClickHouse。
整体上,标签数据进入 ClickHouse 之后,就可以进行人群圈选。根据业务侧应用场景,将标签和人群数据分发到不同的存储。批量推送数据需从ClickHouse 推送至 B 站自研分布式对象存储系统 BOSS 后提供 API 接口访问;实时判定点查数据是从 ClickHouse 推送至 Redis 后提供 API 接口访问;北极星行为分群数据直接从 ClickHouse 提供画像分析能力。
接下来详细介绍一下标签生产、人群圈选和在线服务三部分。
在讲解标签构建之前,先来介绍一下 B 站当前的标签体系情况。
整体目标为让业务能够快速灵活地接入标签。
离线标签构建:
标签构建流程为,所需数据源元信息从 Hive 表接入 Iceberg,连续型标签不再出仓,直接基于 Iceberg 对接实时查询,离散型标签再通过 Spark 计算出仓至 ClickHouse。标签数据主要包括标签 BitMap、分区 logdata 和 version。
整个构建流程通过标签系统进行管理,同时在标签系统中还有对元信息的管理。
再来介绍一下自定义分 shard 的过程。Hive 表和 Iceberg 表数据进入到标签构建,根据用户 id 和 Spark 任务数 hash,得到 n*m 份数据,其中 n 为 ClickHouse 的 shard 数,m 是根据数据量级定义的并发数。之后根据 task id 和 shard 数再次 hash,确定每份 BigMap 数据写到哪里。这样做一方面可以保证构建的速度,另一方面也可以保证一个 id 落到一个 shard 上,后续所有计算、读写都仅用 local 表即可,从而减少表的聚合计算。
标签生产另外一个重要来源是埋点数据。北极星作为 B 站的埋点分析管理平台,负责管理除以上 DB 数据之外的埋点行为数据,用户可以根据选择特定埋点行为条件去圈选出具有某一行为特征的人群,以标签的形式同步到标签系统。
整体流程为,选择埋点行为条件,北极星平台将其翻译为 ClickHouse SQL,对表查询得到 BitMap,再分 shard 写入标签表。整个流程已在系统层面打通,以提升效率。
标签平台支持通过以下 5 种方式创建人群:基于规则和行为的标签圈群、本地文件 csv 导入用户 id、从 Hive 表接入、大数据平台查询获取的 http 链接、同步 DMP 人群包;
人群使用场景包括:批量导出、人群判定、画像分析。批量导出场景下打开人群导出,数据存储至 BOSS 后提供文件下载链接;实时判定等在线服务场景下,打开数据写入线上集群,写入至 Redis 后业务侧通过 API 进行实时点查;画像分析则两者都无需开启。
人群创建的方式决定了人群数据的来源,人群应用的方式则决定了人群数据的存储;
人群更新方式包括:非例行和例行。非例行表示立即执行计算,例行则会根据圈群规则获取上游依赖的标签、人群当日是否更新,等待依赖更新后提交计算。
人群规则确定后,相应请求的 DSL 发送服务端,针对 DSL 配置做 DAG 任务拆解,任务分配到相应队列后处理运算。
规则圈选 DSL 支持的操作运算符如上图所示。
多层级可扩展的 DSL 结构,目前是采用三层结构,在业务实践中几乎可以满足所有场景需求。根据DSL 描述翻译成 Iceberg/ClickHouse 各自节点对应的SQL。
另外,也会进行一些优化。例如 Iceberg 查询优化,假设 A1、A2 均为连续标签,它们来自同一张 Iceberg 表,那么就把这两个标签在模型表的层面做合并计算,最终只会生成一个 Iceberg 任务。
在线服务满足 SLA 标准:
在安全性上支持高并发、高可用,各业务独立限流;在扩展性上支持无状态计算,各业务存储隔离;在满足安全性和水平扩展性的基础上,做到服务全生命周期功能覆盖,包括人群生成灌库、黑白名单、流量控制、版本切换、人群下线等。
在较大数据量下人群数据通过 Spark 写入 Redis。根据人群元信息将数据写入不同 Redis 集群,进行存储隔离。当前在 Redis 层面采用了 KKV 的存储结构。版本控制方面,保留 5 个数据版本,版本更新逻辑为,当前人群 id 版本和当前版本做逻辑与,再去拼接下一个版本。
因为对接 C 端业务,所以要求比较严谨,人群灰度包括流量控制、人群替换和快速回滚。流量控制的场景为,比如一个新功能对某个人群开放,而人群策略不确定是否合理,这时就需要灰度放流,在此过程中观察用户反馈。人群替换的场景为,比如人群策略变更,但对接服务中人群id 不方便修改,这时就可以另外要一个人群来进行替换。数据构建是偏离线的,有一定时间差,如果数据出现问题可以快速回滚到上一个版本。
这三个功能都是基于分流表实现的。
判定请求条件采用的是开源语法分析器 antlr,支持多个人群进行交并差逻辑运算判定。
标签平台整体性能表现如图。离散标签使用的是 ClickHouse,如果用 Iceberg 会相对较慢。对圈选时效性要求比较高的情况下,可以通过将连续标签进一步抽象为离散标签,再使用 ClickHouse 进行计算。
标签平台与其他数据应用产品的集成,对外提供服务,主要为 AB 平台的实验受众人群配置和北极星平台的行为分析场景,均实现了双向数据打通。
人群应用场景包括推送触达、业务运营、业务分析等:
实现标签和人群的热度、血缘的可视化展示,展示数据资产价值的同时可以进一步根据热度排名及孤立血缘,实现标签人群的智能下线功能。
实现标签和人群的分级保障;在标签人群的生产过程中对接大数据平台的 DQC 和基线能力,以完善数据质量治理及任务告警机制。
在标签人群的价值判定上,通过与指标平台对接观察人群对业务指标的影响从而确定人群价值。
标签接入规范化,加强公共标签的建设,实现统一口径;建设标签在跨业务域场景下的分享使用机制,实现标签价值最大化。
TOP