B 站標(biāo)簽系統(tǒng)落地實(shí)踐
一、演進(jìn)歷程
首先簡(jiǎn)要介紹一下 B 站標(biāo)簽系統(tǒng)的演進(jìn)歷程。
1. 2021 年標(biāo)簽系統(tǒng)立項(xiàng)
B 站標(biāo)簽系統(tǒng)建立于 2021 年初。當(dāng)時(shí)立項(xiàng)的背景為,業(yè)務(wù)側(cè)人均取數(shù)的需求越來越多,希望能夠加速數(shù)據(jù)取用的效率,標(biāo)簽系統(tǒng)內(nèi)部立項(xiàng)建設(shè)啟動(dòng)。
在最初的版本中形成了基礎(chǔ)的標(biāo)簽圈群的能力,以開放 API 的方式對(duì)外提供服務(wù),基本上能夠滿足當(dāng)時(shí)的業(yè)務(wù)需求。
隨著越來越多的標(biāo)簽接入需求,以及業(yè)務(wù)側(cè)越來越高的人群圈選頻率,系統(tǒng)逐步面臨各種問題:
- 所有明細(xì)數(shù)據(jù)進(jìn)入 ClickHouse,通過物化視圖的方式做 BitMap 計(jì)算,通過分頁查詢的方式做人群數(shù)據(jù)的導(dǎo)出;另外,以 API 的方式對(duì)外提供服務(wù),前端用戶可能自定義輸入非常復(fù)雜的 SQL,以上操作都會(huì)大量消耗ClickHouse 計(jì)算資源,導(dǎo)致其單引擎部署的計(jì)算負(fù)載面臨的穩(wěn)定性壓力越來越大,集群擴(kuò)展性不佳。
- 隨著對(duì)接的業(yè)務(wù)方定制化需求越來越多,導(dǎo)致 API 存在多套體系,整體維護(hù)成本較高,也很難持續(xù)迭代優(yōu)化。
- 為了提升業(yè)務(wù)圈選響應(yīng)速度,只要有用戶圈選需求進(jìn)入,系統(tǒng)會(huì)立即提交ClickHouse 計(jì)算任務(wù),缺乏任務(wù)并發(fā)度的管控。
2. 2022 年系統(tǒng)重構(gòu)升級(jí)
針對(duì) 2021 系統(tǒng)上線后面臨的問題進(jìn)行點(diǎn)狀優(yōu)化,并通過平臺(tái)化的方式對(duì)接更多業(yè)務(wù)場(chǎng)景。
- 穩(wěn)定性方面:引入多存算引擎的支持,在人群計(jì)算上支持任務(wù)隊(duì)列的調(diào)度,并重新定義了圈選 DSL。
- 場(chǎng)景拓展方面:實(shí)現(xiàn)了實(shí)時(shí)判定能力,對(duì)接 C 端業(yè)務(wù)服務(wù)。
3. 2023 年系統(tǒng)化建設(shè)賦能業(yè)務(wù)
更加系統(tǒng)化地建設(shè)標(biāo)簽系統(tǒng),在業(yè)務(wù)側(cè)更好地打通數(shù)據(jù)平臺(tái)和業(yè)務(wù)應(yīng)用:
- 上下游收斂縮短數(shù)據(jù)鏈路
- 標(biāo)簽人群治理與數(shù)據(jù)質(zhì)量保障
- 人群效果回收與標(biāo)簽體系完善
二、系統(tǒng)架構(gòu)與實(shí)踐
1. 標(biāo)簽系統(tǒng)整體架構(gòu)
系統(tǒng)整體架構(gòu)從下到上可以分為三個(gè)層級(jí):依次為標(biāo)簽生產(chǎn)、人群圈選和人群應(yīng)用。
- 數(shù)據(jù)來源:依托于大數(shù)據(jù)平臺(tái),各種業(yè)務(wù)數(shù)據(jù)例如 DB 數(shù)據(jù)、埋點(diǎn)行為數(shù)據(jù)、AB 實(shí)驗(yàn)分流用戶數(shù)據(jù)等均可接入標(biāo)簽平臺(tái),通過 Spark 、Trino 以及Clickhouse 計(jì)算引擎實(shí)現(xiàn)上層標(biāo)簽生產(chǎn)及人群圈選。
- 標(biāo)簽生產(chǎn):支持?jǐn)?shù)據(jù)源表接入、標(biāo)簽元信息管理、標(biāo)簽構(gòu)建、標(biāo)簽治理。
- 人群圈選:支持人群元信息管理、人群規(guī)則圈選、人群計(jì)算調(diào)度、生命周期管理。
- 人群應(yīng)用:支持?jǐn)?shù)據(jù)批量下載、在線實(shí)時(shí)判定、畫像分析。
- 業(yè)務(wù)應(yīng)用:包括推送平臺(tái)、活動(dòng)和任務(wù)平臺(tái)、用戶洞察、用戶增長等。
2. 數(shù)據(jù)流轉(zhuǎn)鏈路
數(shù)據(jù)流轉(zhuǎn)鏈路是整個(gè)標(biāo)簽系統(tǒng)整體架構(gòu)的核心,標(biāo)簽系統(tǒng)的主要作用是把各種類型的原始數(shù)據(jù)快速生產(chǎn)成人群,最終對(duì)接業(yè)務(wù)側(cè)各種場(chǎng)景的使用。
業(yè)務(wù)數(shù)據(jù),包括 DB 數(shù)據(jù),以及日志和埋點(diǎn)上報(bào)等數(shù)據(jù)。
一方面,業(yè)務(wù)數(shù)據(jù)通過大數(shù)據(jù)的數(shù)據(jù)集成能力入倉得到 Hive 表和 Iceberg 表,再通過標(biāo)簽構(gòu)建,出倉進(jìn)入到 ClickHouse。這是離線的鏈路。
另一方面,移動(dòng)端的埋點(diǎn)數(shù)據(jù)也是依托大數(shù)據(jù)的能力,會(huì)直接進(jìn)入到ClickHouse。
整體上,標(biāo)簽數(shù)據(jù)進(jìn)入 ClickHouse 之后,就可以進(jìn)行人群圈選。根據(jù)業(yè)務(wù)側(cè)應(yīng)用場(chǎng)景,將標(biāo)簽和人群數(shù)據(jù)分發(fā)到不同的存儲(chǔ)。批量推送數(shù)據(jù)需從ClickHouse 推送至 B 站自研分布式對(duì)象存儲(chǔ)系統(tǒng) BOSS 后提供 API 接口訪問;實(shí)時(shí)判定點(diǎn)查數(shù)據(jù)是從 ClickHouse 推送至 Redis 后提供 API 接口訪問;北極星行為分群數(shù)據(jù)直接從 ClickHouse 提供畫像分析能力。
接下來詳細(xì)介紹一下標(biāo)簽生產(chǎn)、人群圈選和在線服務(wù)三部分。
3. 標(biāo)簽生產(chǎn)
在講解標(biāo)簽構(gòu)建之前,先來介紹一下 B 站當(dāng)前的標(biāo)簽體系情況。
整體目標(biāo)為讓業(yè)務(wù)能夠快速靈活地接入標(biāo)簽。
- 建設(shè)思路:對(duì)于事實(shí)屬性類標(biāo)簽,例如性別、年齡、城市等人口屬性、位置屬性標(biāo)簽,由平臺(tái)自建,作為公共標(biāo)簽對(duì)外提供;對(duì)于統(tǒng)計(jì)類、規(guī)則類或模型類標(biāo)簽,即業(yè)務(wù)強(qiáng)相關(guān)的標(biāo)簽,與業(yè)務(wù)部門合作建設(shè)。
- 組織結(jié)構(gòu)分為三級(jí):一級(jí),標(biāo)簽類目;二級(jí),具體標(biāo)簽;三級(jí),標(biāo)簽枚舉。
- 標(biāo)簽分類標(biāo)準(zhǔn):根據(jù)后續(xù)圈選操作不同分為離散與連續(xù)類型。離散標(biāo)簽:枚舉型,如性別;連續(xù)標(biāo)簽:數(shù)值型,如播放時(shí)長。
- 標(biāo)簽權(quán)限管理:基于業(yè)務(wù)域去做歸屬和隔離,用戶只能使用具有授權(quán)的標(biāo)簽。
- 標(biāo)簽接入流程:為滿足業(yè)務(wù)取數(shù)便捷性要求,支持用戶平臺(tái)化自助錄入數(shù)據(jù)源,完成標(biāo)簽和字段綁定、觸發(fā)審批流程。評(píng)估和審批分三個(gè)環(huán)節(jié),各環(huán)節(jié)負(fù)責(zé)人分別是業(yè)務(wù)域負(fù)責(zé)人(關(guān)注標(biāo)簽體系是否完整、合理)、業(yè)務(wù)域數(shù)倉負(fù)責(zé)人(關(guān)注標(biāo)簽數(shù)據(jù)源表及上游模型是否規(guī)范)、標(biāo)簽服務(wù)負(fù)責(zé)人(DQC 規(guī)則配置)。
- 業(yè)務(wù)域:包括基礎(chǔ)域、B 端創(chuàng)作者、大會(huì)員、直播、游戲、漫畫等。
離線標(biāo)簽構(gòu)建:
- 引入 Iceberg 支持多存算引擎的實(shí)時(shí)查詢性能優(yōu)勢(shì),解決集群負(fù)載問題;支持多計(jì)算引擎接入,解決集群擴(kuò)展性差問題。
- 通過自定義分 shard 模式讀寫,避免使用 ClickHouse 分布式表聚合計(jì)算影響性能。
標(biāo)簽構(gòu)建流程為,所需數(shù)據(jù)源元信息從 Hive 表接入 Iceberg,連續(xù)型標(biāo)簽不再出倉,直接基于 Iceberg 對(duì)接實(shí)時(shí)查詢,離散型標(biāo)簽再通過 Spark 計(jì)算出倉至 ClickHouse。標(biāo)簽數(shù)據(jù)主要包括標(biāo)簽 BitMap、分區(qū) logdata 和 version。
整個(gè)構(gòu)建流程通過標(biāo)簽系統(tǒng)進(jìn)行管理,同時(shí)在標(biāo)簽系統(tǒng)中還有對(duì)元信息的管理。
再來介紹一下自定義分 shard 的過程。Hive 表和 Iceberg 表數(shù)據(jù)進(jìn)入到標(biāo)簽構(gòu)建,根據(jù)用戶 id 和 Spark 任務(wù)數(shù) hash,得到 n*m 份數(shù)據(jù),其中 n 為 ClickHouse 的 shard 數(shù),m 是根據(jù)數(shù)據(jù)量級(jí)定義的并發(fā)數(shù)。之后根據(jù) task id 和 shard 數(shù)再次 hash,確定每份 BigMap 數(shù)據(jù)寫到哪里。這樣做一方面可以保證構(gòu)建的速度,另一方面也可以保證一個(gè) id 落到一個(gè) shard 上,后續(xù)所有計(jì)算、讀寫都僅用 local 表即可,從而減少表的聚合計(jì)算。
標(biāo)簽生產(chǎn)另外一個(gè)重要來源是埋點(diǎn)數(shù)據(jù)。北極星作為 B 站的埋點(diǎn)分析管理平臺(tái),負(fù)責(zé)管理除以上 DB 數(shù)據(jù)之外的埋點(diǎn)行為數(shù)據(jù),用戶可以根據(jù)選擇特定埋點(diǎn)行為條件去圈選出具有某一行為特征的人群,以標(biāo)簽的形式同步到標(biāo)簽系統(tǒng)。
整體流程為,選擇埋點(diǎn)行為條件,北極星平臺(tái)將其翻譯為 ClickHouse SQL,對(duì)表查詢得到 BitMap,再分 shard 寫入標(biāo)簽表。整個(gè)流程已在系統(tǒng)層面打通,以提升效率。
4. 人群圈選
標(biāo)簽平臺(tái)支持通過以下 5 種方式創(chuàng)建人群:基于規(guī)則和行為的標(biāo)簽圈群、本地文件 csv 導(dǎo)入用戶 id、從 Hive 表接入、大數(shù)據(jù)平臺(tái)查詢獲取的 http 鏈接、同步 DMP 人群包;
人群使用場(chǎng)景包括:批量導(dǎo)出、人群判定、畫像分析。批量導(dǎo)出場(chǎng)景下打開人群導(dǎo)出,數(shù)據(jù)存儲(chǔ)至 BOSS 后提供文件下載鏈接;實(shí)時(shí)判定等在線服務(wù)場(chǎng)景下,打開數(shù)據(jù)寫入線上集群,寫入至 Redis 后業(yè)務(wù)側(cè)通過 API 進(jìn)行實(shí)時(shí)點(diǎn)查;畫像分析則兩者都無需開啟。
人群創(chuàng)建的方式?jīng)Q定了人群數(shù)據(jù)的來源,人群應(yīng)用的方式則決定了人群數(shù)據(jù)的存儲(chǔ);
人群更新方式包括:非例行和例行。非例行表示立即執(zhí)行計(jì)算,例行則會(huì)根據(jù)圈群規(guī)則獲取上游依賴的標(biāo)簽、人群當(dāng)日是否更新,等待依賴更新后提交計(jì)算。
人群規(guī)則確定后,相應(yīng)請(qǐng)求的 DSL 發(fā)送服務(wù)端,針對(duì) DSL 配置做 DAG 任務(wù)拆解,任務(wù)分配到相應(yīng)隊(duì)列后處理運(yùn)算。
規(guī)則圈選 DSL 支持的操作運(yùn)算符如上圖所示。
多層級(jí)可擴(kuò)展的 DSL 結(jié)構(gòu),目前是采用三層結(jié)構(gòu),在業(yè)務(wù)實(shí)踐中幾乎可以滿足所有場(chǎng)景需求。根據(jù)DSL 描述翻譯成 Iceberg/ClickHouse 各自節(jié)點(diǎn)對(duì)應(yīng)的SQL。
另外,也會(huì)進(jìn)行一些優(yōu)化。例如 Iceberg 查詢優(yōu)化,假設(shè) A1、A2 均為連續(xù)標(biāo)簽,它們來自同一張 Iceberg 表,那么就把這兩個(gè)標(biāo)簽在模型表的層面做合并計(jì)算,最終只會(huì)生成一個(gè) Iceberg 任務(wù)。
5. 在線服務(wù)
在線服務(wù)滿足 SLA 標(biāo)準(zhǔn):
在安全性上支持高并發(fā)、高可用,各業(yè)務(wù)獨(dú)立限流;在擴(kuò)展性上支持無狀態(tài)計(jì)算,各業(yè)務(wù)存儲(chǔ)隔離;在滿足安全性和水平擴(kuò)展性的基礎(chǔ)上,做到服務(wù)全生命周期功能覆蓋,包括人群生成灌庫、黑白名單、流量控制、版本切換、人群下線等。
在較大數(shù)據(jù)量下人群數(shù)據(jù)通過 Spark 寫入 Redis。根據(jù)人群元信息將數(shù)據(jù)寫入不同 Redis 集群,進(jìn)行存儲(chǔ)隔離。當(dāng)前在 Redis 層面采用了 KKV 的存儲(chǔ)結(jié)構(gòu)。版本控制方面,保留 5 個(gè)數(shù)據(jù)版本,版本更新邏輯為,當(dāng)前人群 id 版本和當(dāng)前版本做邏輯與,再去拼接下一個(gè)版本。
因?yàn)閷?duì)接 C 端業(yè)務(wù),所以要求比較嚴(yán)謹(jǐn),人群灰度包括流量控制、人群替換和快速回滾。流量控制的場(chǎng)景為,比如一個(gè)新功能對(duì)某個(gè)人群開放,而人群策略不確定是否合理,這時(shí)就需要灰度放流,在此過程中觀察用戶反饋。人群替換的場(chǎng)景為,比如人群策略變更,但對(duì)接服務(wù)中人群id 不方便修改,這時(shí)就可以另外要一個(gè)人群來進(jìn)行替換。數(shù)據(jù)構(gòu)建是偏離線的,有一定時(shí)間差,如果數(shù)據(jù)出現(xiàn)問題可以快速回滾到上一個(gè)版本。
這三個(gè)功能都是基于分流表實(shí)現(xiàn)的。
判定請(qǐng)求條件采用的是開源語法分析器 antlr,支持多個(gè)人群進(jìn)行交并差邏輯運(yùn)算判定。
6. 標(biāo)簽系統(tǒng)穩(wěn)定性與性能
標(biāo)簽平臺(tái)整體性能表現(xiàn)如圖。離散標(biāo)簽使用的是 ClickHouse,如果用 Iceberg 會(huì)相對(duì)較慢。對(duì)圈選時(shí)效性要求比較高的情況下,可以通過將連續(xù)標(biāo)簽進(jìn)一步抽象為離散標(biāo)簽,再使用 ClickHouse 進(jìn)行計(jì)算。
三、人群應(yīng)用
1. 數(shù)據(jù)應(yīng)用集成
標(biāo)簽平臺(tái)與其他數(shù)據(jù)應(yīng)用產(chǎn)品的集成,對(duì)外提供服務(wù),主要為 AB 平臺(tái)的實(shí)驗(yàn)受眾人群配置和北極星平臺(tái)的行為分析場(chǎng)景,均實(shí)現(xiàn)了雙向數(shù)據(jù)打通。
2. 業(yè)務(wù)場(chǎng)景應(yīng)用
人群應(yīng)用場(chǎng)景包括推送觸達(dá)、業(yè)務(wù)運(yùn)營、業(yè)務(wù)分析等:
- 推送觸達(dá):通過短信及站內(nèi)消息等渠道對(duì)特定人群包進(jìn)行批量推送。
- 業(yè)務(wù)運(yùn)營:利用實(shí)時(shí)判定能力,在活動(dòng)中臺(tái)及直播任務(wù)平臺(tái)等進(jìn)行業(yè)務(wù)運(yùn)營推廣策略的落地。
- 分析:包括畫像分析、自定義分析等。
四、未來規(guī)劃
1. 標(biāo)簽人群治理
實(shí)現(xiàn)標(biāo)簽和人群的熱度、血緣的可視化展示,展示數(shù)據(jù)資產(chǎn)價(jià)值的同時(shí)可以進(jìn)一步根據(jù)熱度排名及孤立血緣,實(shí)現(xiàn)標(biāo)簽人群的智能下線功能。
2. 數(shù)據(jù)質(zhì)量保障
實(shí)現(xiàn)標(biāo)簽和人群的分級(jí)保障;在標(biāo)簽人群的生產(chǎn)過程中對(duì)接大數(shù)據(jù)平臺(tái)的 DQC 和基線能力,以完善數(shù)據(jù)質(zhì)量治理及任務(wù)告警機(jī)制。
3. 人群效果回收
在標(biāo)簽人群的價(jià)值判定上,通過與指標(biāo)平臺(tái)對(duì)接觀察人群對(duì)業(yè)務(wù)指標(biāo)的影響從而確定人群價(jià)值。
4. 標(biāo)簽體系完善
標(biāo)簽接入規(guī)范化,加強(qiáng)公共標(biāo)簽的建設(shè),實(shí)現(xiàn)統(tǒng)一口徑;建設(shè)標(biāo)簽在跨業(yè)務(wù)域場(chǎng)景下的分享使用機(jī)制,實(shí)現(xiàn)標(biāo)簽價(jià)值最大化。