tft每日頭條

 > 科技

 > 程序員必備的十大技術

程序員必備的十大技術

科技 更新时间:2024-09-01 02:19:01

為什麼要做個性化推薦

回顧彈幕工程建設的發展曆程,大緻可以分幾個階段:

1. 基礎能力:在高并發、熱點場景下,保證彈幕服務的穩定和高可用

2. 負向治理:以管控為目标,通過删除、自檢、打薄等手段過濾低質彈幕内容

3. 正向推薦:以優化視頻消費體驗為目标,篩選優質彈幕内容上屏展示這三個階段的目标始終在并行推進,在1和2的基本問題完成之後,作為B站的特色功能和社區文化重要載體,彈幕業務在承接基礎功能之外也需要持續探索優化消費體驗的能力。這也就必須在稿件維度優選的基礎上通過用戶特征交互獲得更大的策略空間,建設千人千面的彈幕推薦能力。這個過程離不開工程、算法、産品等多個團隊的傾力合作,本文會以工程團隊的視角重點介紹工程架構對推薦系統的能力支持。

第一階段:基于原架構構建推薦能力

這一階段,我們基于原有架構搭了一個最簡版的推薦能力:

程序員必備的十大技術(百億數據個性化推薦)1

發送彈幕時,工程系統通過數據庫binlog同步給推薦系統。在展示側,由推薦系統負責計算對應視頻要展示的彈幕id列表,工程系統獲取彈幕内容最終返回。這樣就實現了一個具備基礎能力的彈幕推薦系統。

這一階段的線上表現還有很大的提升空間。主要原因是當時的彈幕系統依賴一個彈幕池的設計,基于視頻的長度确定一個視頻内可展示彈幕數的上限。當彈幕池滿了,會按照時間倒序淘汰,留下最新的N條。舉個例子,一個15分鐘長度的視頻,彈幕池上限是6000條。這個設計會帶來以下的問題:

1. 可展示彈幕少

由于彈幕池上限比較小并且分布不均勻,經常出現彈幕填不滿屏幕的情況。

2. 彈幕質量差,優質曆史彈幕無法召回

因為彈幕池整體較小,候選集有限,選出優質内容的空間較小。同時因為時間序淘汰,很多優質的彈幕内容無法沉澱下來。

3. 彈幕分布不均勻,長視頻出現空屏

舉個例子,很多長視頻比如ogv,大量彈幕集中出現在開屏打卡。這部分重複内容會把整個視頻的彈幕池擠掉,導緻後面大段内容出現彈幕空屏。

這些問題,我們會在下一個階段着重優化解決。

第二階段:10倍擴大召回池

在前一個階段,我們發現了基于原有彈幕池工程基建去搭建個性化推薦的問題。我們決定重新搭建一套專門服務于個性化推薦的工程系統。整體架構如下,後面會逐步展開介紹。

程序員必備的十大技術(百億數據個性化推薦)2

2.1 原彈幕系統

先簡單介紹一下原彈幕系統的工程實現。彈幕的兩個核心場景是,發彈幕時以彈幕維度的唯一id(彈幕id)作為主鍵落庫,同時關聯視頻id;在讀彈幕時,一次性讀取一個視頻6分鐘分片的全部彈幕,以視頻 分片維度讀取。作為B站的核心功能,彈幕的讀寫場景都要随時應對高并發流量以及突發的熱點場景。原有架構的存儲系統主要用了一套三級緩存的結構:

程序員必備的十大技術(百億數據個性化推薦)3

第一級接口級緩存直接承接C端讀流量。在第一級緩存miss之後,先通過第二級緩存獲取當前視頻分片的彈幕id列表,然後從第三級緩存獲取獲取具體的彈幕内容。在第二級緩存到第三級緩存之間存在彈幕數量的讀放大,若當前視頻的6分鐘分片有1000條彈幕,就會産生1000倍的讀放大。若第三級緩存發生miss,則會回源到底層存儲TiDB。這套架構存儲相對複雜,因為彈幕池的存儲強依賴于Memcached和Redis zset,在容量擴展上,很難支持個性化推薦的業務訴求。同時視頻維度時間序淘汰這一固定邏輯也很難變更。這一階段我們也思考過通過AI側的彈幕質量粗排模型打分來代替時間序淘汰,但在現有架構下,整體數據刷新的複雜度、模型實驗能力的支持、模型版本更新的數據回刷都成為瓶頸點。

2.2 個性化推薦彈幕系統

程序員必備的十大技術(百億數據個性化推薦)4

基于上述問題,我們決定重新搭建一套彈幕的個性化推薦系統。新系統在展示側的核心鍊路不變,仍然是通過AI的精排接口獲取彈幕ID,在内部存儲系統中讀取彈幕内容,渲染并返回。新系統的核心目标是最大限度擴大推薦系統的召回池容量,同時選用基于模型的召回策略并支持回刷。在實現上,核心思路是簡化存儲并提升計算能力,後面也會主要以存儲和計算兩方面進行介紹。

2.2.1 存儲設計

程序員必備的十大技術(百億數據個性化推薦)5

新系統的職責邊界是隻滿足讀彈幕的個性化推薦這一個最核心場景,因而在存儲上不需要存全量彈幕,也不需要支持複雜的業務邏輯和查詢能力。基于這樣的場景特點,我們放棄了關系查詢支持,選擇了B站自研的KV數據庫泰山,将一個視頻一分鐘内經過召回的彈幕存在一個key裡面。同時,單條彈幕也以彈幕id作為key進行存儲,用于處理彈幕狀态或其他元數據的更新。因為KV數據庫不支持事務,我們自己通過redis分布式鎖保證了并發場景下的數據一緻性。受益于KV數據庫強大的讀寫并發能力,在場景有讀放大的情況下,我們仍然選擇了不加緩存直連數據庫的最簡單存儲結構。最終線上表現,DB完全可以承受百萬QPS的并發訪問量。

2.2.2 計算優化

原系統中,如果彈幕池存滿是基于時間序倒序淘汰。在新系統中,我們選擇視頻每10秒鐘的彈幕作為最小的策略單元,可支持10秒1000條彈幕的召回空間,按照AI策略提供的粗排模型打分進行淘汰。這樣做的一個問題是,一旦粗排模型有邏輯更新,需要重新刷新召回池。為此,我們設計了全量回刷模塊。AI通過離線Hive獲取全量彈幕,打分并推送至工程側,重新計算淘汰策略并進行存儲。經過線上驗證,更新百億以上的彈幕數據大概需要2天左右。增量數據更新模塊中,我們通過消息隊列聚合的方式減輕數據庫的寫入壓力,通過redis分布式鎖保證召回池全量回刷期間增量數據也同時更新的數據一緻性。

2.2.3 分片顆粒度選擇

在個性化推薦的系統中,多處使用到了分片的概念,用來聚合單位視頻長度下的彈幕内容。我們對分片的大小做了不同的選型:在接口層,如果一次下發的分片過長會造成帶寬浪費,比如下發10分鐘的彈幕,用戶看1分鐘就退出了。但如果分片過小,又會因為請求輪詢導緻服務端QPS變大。這裡我們一開始用了6分鐘的分片大小,後來優化為服務端根據場景動态下發分片大小,從而節約帶寬。同樣,在存儲上我們主要的平衡點是讀數據時的請求放大和數據更新時的顆粒度。在一個存儲單元内部,我們以每10秒作為一個策略單元進行彈幕淘汰,主要為了滿足策略目标,讓彈幕足量且均勻。

程序員必備的十大技術(百億數據個性化推薦)6

2.2.4 雙系統關系

線上維持兩套系統的常見問題是職責邊界和關系不清晰,導緻在疊代中逐漸走向混亂。我們在設計階段就對兩套系統做了明确的職責劃分和關系定義:原彈幕系統負責整體的彈幕業務邏輯,新系統(圖中個性化推薦彈幕系統)隻為個性化推薦這一個場景服務。在存儲上,原系統以TiDB存儲全量彈幕内容作為source of truth,新系統的KV數據庫作為個性化推薦的召回池,是TiDB數據庫的子集。同時,在彈幕消費這一主要場景下,原系統以線上熱備的形式維護。在個性化推薦系統出現故障時,可以自動降級使用戶側無感。

2.3 核心收益

這套架構通過召回池存儲容量的整體擴充,以及視頻維度彈幕淘汰到視頻每10秒維度淘汰的策略顆粒度提升,最直觀的收益是彈幕召回池的上線擴充,是原來的10倍左右。假設視頻是15分鐘,彈幕上限就從整個視頻6000條升級到每10秒1000條,曝光上漲30%,大大提升了消費體驗。很好理解,1w選1000和10w選1000的最終質量是完全不一樣的。在穩定性上,我們通過策略降級、工程指标降級以及雙系統保障等手段,從上線至今沒有出現過全站事故。當然,業務上最核心的收益是工作思路轉變:個性化推薦提供了一個工作通路,可以通過彈幕持續優化視頻的消費體驗、社區互動氛圍和UP主滿意度。

第三階段:工程架構和推薦系統深度結合

在上一個階段,主要通過優化工程系統提升了個性化推薦的能力支持。經過一段時間的應用,我們發現系統中還存在一些問題,主要有:

1. 工程和AI的數據不對齊。線上經常出現,精排返回的彈幕id在工程系統的召回池中獲取不到。經過排查我們發現,核心問題是工程和AI兩邊對召回和淘汰各自實現。工程側的召回池通過上述彈幕池分片進行存儲,AI側在系統内部通過離線hdfs存儲。雖然工程側是依據AI的粗排模型進行召回并淘汰,但随着AI的召回策略疊代,兩邊的策略一緻性和數據一緻性都很難有效保證。

2. AI側系統降級頻繁。核心原因主要有兩個方面,一是模型打分的存儲架構不夠合理,二是在精排階段缺少實時退場能力。AI側的模型索引通過hdfs文件系統存儲,每次索引服務啟動時熱加載到内存中。顯而易見的問題是啟動效率低且不穩定,且難以支持水平擴展。同時在精排階段沒有做退場淘汰,遇到熱點視頻時經常出現響應超時甚至OOM。

3. 實驗能力不足。當前的工程系統可以通過全量數據回刷的方式來對策略疊代做最基礎的支持。但是B站全量彈幕在百億以上,回刷一次需要2-3天完成,這顯然無法支持快速策略疊代的業務訴求。這三個表象問題都指向了工程側和AI側結合之後的系統問題,因此我們這一階段的主要思路是以工程和AI結合的整體視角來對系統進行設計優化。

3.1 彈幕推薦的場景分析

首先我們重新調研一下彈幕推薦的場景特點,以及和B站的核心内容推薦場景,視頻推薦的比較。在第一、二階段,工程和算法系統的交互模式以參考視頻推薦的主流方式為主:工程側在生産(發送)内容時通過binlog訂閱同步給算法側,在展示場景下調用算法側接口獲取id列表,兩邊類似黑盒模式,各自進行疊代和優化。我們比較一下兩個場景的特點和工程要求:

程序員必備的十大技術(百億數據個性化推薦)7

視頻推薦是動态推理,即将随着視頻播放不斷産生的交互數據用于模型更新。彈幕推薦是靜态推理,即在彈幕發送時就計算好全部的模型分數,不随着線上數據進行變更。這一點上,視頻推薦的推理策略複雜度更高,而彈幕推薦的場景下更适合通過批量任務的方式優化離線模型分數的計算和存儲。同時,内容查詢複雜度、數量級、QPS和響應時間幾個方面彈幕系統都需要滿足更高的要求。在整體流程上,都由召回、粗排、精排這3個主要步驟構成,在召回和粗排階段完成模型計算,在精排階段進行用戶特征的實時交互,從而實現個性化。

3.2 設計目标&核心思路

根據這上述的場景特點,我們決定打破之前工程和算法互相黑盒的常規設計模式,在整體視角下調整架構設計,在模塊級别通過職能進行分工。由工程團隊負責高并發的數據讀取,以及各類實時、離線任務的更新;算法團隊專注負責計算策略,包括模型推理和精排。這樣兩個團隊都可以發揮自己的優勢,将整個系統做好。首先介紹一些核心概念:

彈幕物料:指彈幕的基礎數據,包括内容、狀态、點贊、舉報、屬性标記等。

彈幕索引:指彈幕的全部模型打分,包含基線模型(即粗排模型)、點贊模型、舉報模型、内容相關模型等,主要用于精排計算。目前每條彈幕大概有15-20組模型打分。

物料池:指一個視頻分片(一分鐘)内所有彈幕物料的集合。

索引池:和物料池類似,一個視頻分片(一分鐘)内所有彈幕索引的集合。

程序員必備的十大技術(百億數據個性化推薦)8

上圖将第二階段架構圖中的AI系統進行了詳細展開。AI系統主要由打分服務、索引服務、精排服務三塊構成,其中打分服務和精排服務主要負責模型和策略,索引服務負責數據召回、粗排淘汰和數據讀寫。在數據上,用戶和稿件特征可以複用公司成熟的平台能力,彈幕索引目前以自建hdfs 内存的方式存儲。再結合上述遺留問題和場景分析,核心思路是将目前的系統瓶頸點,負責數據讀寫的索引服務以及對應的數據存儲合并到工程系統中。主要設計目标如下:

1. 合并物料池、索引池:解決物料池、索引池各自進行淘汰導緻的數據不對齊問題。

2. 精排優化:前置精排退場邏輯,解決熱點場景下OOM導緻精排不可用的問題。

3. 提升實驗效率:提供小時級模型更新實驗能力,支撐策略快速疊代。

3.3 詳細設計

3.3.1 發送、展示鍊路簡要流程

程序員必備的十大技術(百億數據個性化推薦)9

3.3.2 個性化推薦彈幕系統模塊展開

程序員必備的十大技術(百億數據個性化推薦)10

3.3.3 實時數據存儲優化

在索引池的合并上,因為讀寫場景一緻,我們選擇了和物料池同樣的kv數據庫(taishan)實現,也是在一個視頻id 分鐘作為key的單位下,對應物料池的粗排分排序淘汰進行存儲。這裡物料池和索引池用不同的key來存,沒有使用在物料池的基礎上擴展字段來實現,核心原因是:

1. 物料和主要業務數據庫tidb、各業務場景下的彈幕模型保持一緻,避免排序索引和業務功能的耦合。

2. 可實現索引、物料獨立更新,降低索引回刷成本。

3. 分梯度降級保證可用性,一旦出現事故索引失效,可以随機打分降級保證C端無感。同時,物料池、索引池兩者的一緻性通過redis分片鎖保證,它的顆粒度是視頻 分鐘,和物料池、索引池key的顆粒度相同,從而在業務存在高并發,且線上增量數據和物料、索引回刷同時進行的情況下實現視頻每分鐘的彈幕原子性寫入。在優先級上以物料池為主,寫入索引前先驗證物料存在,反之則不做強校驗。

3.3.4 實驗能力支持

我們設計了三個不同的數據回刷鍊路:增量數據更新、索引回刷、物料回刷。其中增量數據更新應用于實時發送的彈幕打分落表,索引回刷應用于在召回、粗排策略不變的情況下刷新一組(或多組)模型打分,物料回刷應用于粗排模型更新時通過全量彈幕重新計算召回和粗排淘汰。業務上出現的主要場景是,如何快速支持粗排模型外的一組模型分數更新。在之前一期的設計中,我們需要對全部的存量數據進行回刷,因此耗時非常久。針對這一特點,我們拆分了索引回刷和物料回刷,區别是是否需要更新粗排模型,重新進行召回和淘汰。這樣通過索引回刷即可滿足大部分策略疊代需求,減輕了整體的流程。結合前面物料池、索引池分離的存儲設計,可以減少了一半的數據寫入量。

索引回刷設計

消費端的一個特點是流量集中在頭部稿件,因此我們的思考方向是如何通過盡量小的數據回刷來覆蓋盡量多的vv百分比。在新的系統中,通過ETL任務計算得到小時更新的高熱稿件(即視頻)表,再通過Clickhouse存儲當天的實時增量數據,這樣兩者結合即可得到完整的高熱 實時視頻列表,在需要更新索引時隻需要更新這部分視頻對應的彈幕即可。通過上述冷熱數據分離的方式,我們最終通過15%計算量可以覆蓋90%的vv,大幅提升了實驗效率。此外,部分策略疊代并不需要刷新全部視頻下的彈幕。在這種情況下,通過數倉更新定制化的ETL并投遞到數據消費端即可,在1小時内即可完成策略更新。

計算量優化

在推薦系統中,模型推理的計算成本也是一項重要考量,如果能節省掉冗餘的推理次數,可以提升整個系統的效率,同時降低運維成本。在前一個階段,計算一條彈幕所有模型打分的方式是并發進行所有模型的推理。但如果這條彈幕最終因粗排分過低而淘汰,則會造成計算冗餘。新系統中的優化方式是,在增量數據更新和物料回刷的過程中,先進行粗排模型分的推理,完成排序淘汰之後再進行全部的模型推理,從而優化計算量。

3.3.5 精排優化

精排場景的難點是如何處理熱點視頻下大批量數據的計算和排序問題。一些爆火的視頻會出現總長度20分鐘左右,單視頻彈幕量超過100w的情況,且集中在視頻開頭。同時各組模型分數的覆蓋、刷新情況也不盡相同,如何在單組模型推理邏輯出錯、部分數據已經寫入索引的情況下保證業務可快速恢複降級也是精排階段的目标之一。

退場邏輯前置

之前的架構中,精排服務器在内存中緩存彈幕索引且沒有退場淘汰邏輯,成為了熱點下的性能瓶頸。在新的系統中,我們将退場邏輯收斂到粗排階段,精排時不再需要進行數據緩存,隻需讀取經過粗排淘汰後的物料和緩存即可。這樣,在精排階段需要排序的數據量大大減少,從而優化了響應時間。

模型版本控制

彈幕索引的模型是離線更新,如果新的模型出現邏輯錯誤隻能在精排階段通過業務指标分組異常發現。而這時極有可能數據刷新已經完成或者進行了一半。為了解決這種場景下的模型策略疊代可灰度、可觀測、可回滾,我們通過彈幕索引的字段冗餘和版本控制來實現:

程序員必備的十大技術(百億數據個性化推薦)11

假設目前線上有點贊模型、負向模型2個模型,本次需要更新負向模型版本,則:更新版本(version 1),新版負向模型更新在空白字段score16,同時保留舊版負向模型score2。模型内容和分數字段的映射關系在精排服務内維護。若發現新版模型不符合預期,則更新映射關系,使用舊版模型字段score2即可完成回滾。若經線上驗證新版模型符合預期,則打分服務服務停止對舊模型)生成打分,同時在精排服務中标記舊模型字段為空白即可完成發布。

展示側召回補充

在前面索引回刷的設計中提到,為了支持快速實驗策略疊代模型回刷會覆蓋大多數視頻而非全量視頻。如果一些冷的視頻又火了起來,需要有方法能發現這些視頻,并且覆蓋最新的模型策略。這裡的實現是,在精排服務中校驗索引的版本(即version字段)。若version過低,将視頻id推送到補召回隊列中,更新全部最新的模型打分。這樣就實現了冷熱數據的轉換。

收益與展望

經過工程和算法系統的整合,數據一緻性、穩定性都獲得了大幅提升。精排降級率從3%下降到了0.1%,在策略不變的情況下彈幕曝光也有大幅增長,再通過減少曝光、提升上屏彈幕質量的方式優化了彈幕點贊率。同時全站策略實驗可以在10小時内完成數據回刷,小規模策略疊代可以在一小時内完成。同時在新的系統中,彈幕點贊、舉報、狀态、屬性位這些特征可以做到實時而非離線,從而提升策略空間和流量冷啟動的效率。在未來,我們也會在策略疊代效率、特征實時性和工程穩定性三個方面對系統進行持續優化探索,從而帶來更優質的彈幕消費體驗

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关科技资讯推荐

热门科技资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved