Twitter推薦引擎架構設計分析

码农谈IT發表於2024-03-05


來源:JavaEdge

0 前言

可靠性保障是複雜的系統工程,尤其可靠性已異常的線上服務,在業務迭代、成本約束、人力投入等方面的約束下 ,提升可用性就不再純技術問題。

推薦引擎作為各類推薦業務線上服務的樞紐環節支援推特熱門流、小影片後推薦等業務,快速迭代時,可靠性問題逐漸暴露。隨業務需求變化,物料規模、已讀過濾等逐漸成為限制迭代的瓶頸點。頻發的抖動與當機,快速膨脹程式碼量,極大消耗開發精力。多重壓力下,推薦引擎滑向失控邊緣。

研發中心基礎架構部架構師分享推特推薦引擎在數月的時間裡從不可控回到可控,可用性由不足2 個9提升至3個9,同時提升業務支援能力的經驗,幫你係統性解決可靠性問題。

1 推薦引擎架構

推特推薦引擎服務於推特各類推薦業務,如服務熱門流、熱點流、影片後推薦等,是推薦系統的樞紐,需結合特徵、模型、物料等環節驅動業務執行,架構圖:

Twitter推薦引擎架構設計分析

使用者請求推薦內容時,先到達推薦前端,隨後在總控開啟推薦流程:

  • 總控會獲取本次重新整理相關的資訊,如使用者興趣、引流推特特徵、已讀資訊等

  • 總控將相關資訊輸入召回引擎,召回引擎根據這些資訊獲得備選推特 ID。召回分為:

    • 標籤召回,即根據使用者資訊、熱點業務規則進行排序
    • 模型召回,即變換資料形式,用向量的方式透過本地或遠端模型服務獲取物料
  • 獲取備選 ID 後,排序引擎先補充相關特徵資訊將備選 ID 構造成完整物料,透過 Hash 等方式將之轉化為可供排序模型使用的特徵向量,送到排序模型打分,完成排序

  • 總控在插入廣告後透過前端填充內容,完成推薦

訓練將接收引擎及客戶端使用者行為日誌,實時更新排序、召回模型;物料將實時更新物料庫,將特徵的更新總結為物料包流和更新流,供引擎實時更新和載入。

2 推薦引擎可靠性挑戰

推特推薦引擎快速迭代中暴露的問題主要是:穩定性和。

2.1 穩定性

表現為單臺引擎(如前文排序引擎)工作幾個小時後即會發生一次當機、記憶體溢位、超時啟停等問題。如有突發流量更疲於應對。此外,當時物料規模、已讀儲存能力等方面的設計已無法滿足現在業務需求。

2.2 業務支援

改造系統比打造新系統更難,不僅需要梳理數 10 萬行程式碼,同時改造中系統還在迭代不能下線,再加上團隊人力不足,外部的壓力(如公司對成本、機器利用率等的要求)等,該問題已經超越技術問題。

3 系統可靠執行的因素

質量

  • 架構
  • 程式碼質量

工具:

  • 治理
  • 擴縮容

人力:

  • 運維
  • 監控

線上系統穩定執行依賴於三個方面:系統本身架構設計和程式碼的質量;自動化的工具(如擴縮容、異常治理等);運維、監控人員人力。三方面如木桶,有一個長板即可支援較大流量:若系統健壯則執行時必然問題較少或若運維人力足沛也可解決多數問題。

多數公司難100%保證某一長板,需結合公司具體情況保證基本質量,出現錯誤時多數依靠工具解決,少數依靠運維人員。對當時的推特推薦引擎,質量是核心問題,但投入大、見效慢;雖有如異常處置等簡單工具建設,但組織簡單且互有衝突,甚至無擴縮容工具,開發空間大,只需適配推特內部成熟工具體系,即可乘高決水,事半功倍;也急需從0到1引入運維團隊。

4 改造實踐

推特推薦引擎改造分為三階段:

  • 透過工具建設先穩住系統,保障後期改造的精力
  • 集中人力大量重寫核心環節,提升系統質量
  • 再次最佳化工具建設,降低維護穩定所需人力

來看:物料儲存結構改造、已讀服務改造和擴縮容工具。

初始階段,我們接入了推特成熟的運維工具,組合了原有自動處置工具、最佳化了上線指令碼,實現了基於 QPS 和超時率的簡單自動縮擴容功能。

4.1 質量改造-物料

排序引擎執行的第一步為將物料初始化為帶特徵的物料,一次需處理數萬條資料,原物料攜帶特徵多,一次請求所需資訊量大,因此選擇單機儲存所有物料。

儲存原使用基於記憶體對映的外部儲存引擎。該引擎溝通速度慢,溝通佔用大,有記憶體效能問題(推特推薦引擎的核心問題所在),限制物料規模。因此重寫該引擎,考慮到:

  • 單條物料儲存
  • 整體物料儲存

物料的特徵:特徵數量數百但平均填充率較低,整體資料較稀疏,大量特徵為字串型。若用類實現則稀疏資料造成記憶體浪費,大量字串造成記憶體碎片,長期使用無法保證穩定性。因此物料結構設計需滿足:

  • 記憶體需連續不可有碎片
  • 稀疏情況下空間的節約
  • 不可影響系統效能

實現如下圖的二級索引結構:

Twitter推薦引擎架構設計分析如圖將物料分成了四段:

  • 白色為頭部,儲存基本資訊
  • 紅色為一級索引
  • 黃色為二級索引
  • 綠色為實際資料段

該結構一級索引為 Bitmap,每一位均可表示是否有一個欄位存在物料中,實現了稀疏的支援。二級索引為所有存在欄位的偏移量位置:

  • 對字串為編譯量
  • 對數字或浮點數儲存資料本身,保證了儲存速度
  • 該儲存結構記憶體連續

滿足了上述三條要求。整體物料儲存用Concurrent HashMap結構,更新速度可達數萬/s,滿足物料數量要求。

4.2 質量改造-已讀

已讀功能,推薦流程的核心環節,推薦系統需要依賴使用者已讀資料,將使用者未讀內容排序。推特推薦系統原已讀是基於 bloom filter 實現。

Twitter推薦引擎架構設計分析

如圖為推特原 30 天已讀方案例項:共四個 filter,每十天儲存一個 filter,每次讀取覆蓋最近 30 天的四個 filter,取回 bloom filter 後透過或運算將其合併成一個 bloom filter 供後續業務使用。

該方案:

  • 結構不合理,面對所有使用者 bloom filter 大小均不變,因此:高消費的使用者使用推特頻率高,填充率高,則誤判高;低消費使用者閱讀量小,空間利用率低,浪費資源
  • 直接讀取儲存的 Redis,儲存一旦出錯服務也難免受牽連,穩定性差
  • 各業務直接讀取資源本身,判斷邏輯需各服務獨立實現

因此改造:

  • 以讀獨立成為一個服務,各個業務調取服務而非快取;將常用判斷邏輯封裝為 SDK,便於業務改動
  • 儲存方式保持 bloom filter,但串的長度和單位大小均可變。在寫入時不按照固定時長寫入,而是前一個 filter 填充率達到閾值時才開啟一個新的 bloom filter,根據前一個 filter 填充速度選擇下一個 filter 的大小。如此可安全節省原來一半以上的空間:高消費使用者 bloom filter 串雖較長,但體積也會較大,可減少誤判;超高消費使用者限制最大串長度,已讀記錄時長雖會縮短,但是能保證其已讀內容相對長久;低消費使用者可用較小的 bloom filter 完成已讀記錄
  • 穩定性,一方面建立獨立的短期(如幾個小時)已讀儲存,在主要資源不可用時提供降級服務;另一方面,最佳化 Redis 資源訪問方式,Meta 資訊及最新一個 bloom fileter 需從主庫讀取,保證資訊時效性,已不更新的其他資訊讀取從庫即可,可緩解 Redis 的儲存資源

4.3 外部工具-擴縮容

應對問題:

  • 日常流量波動,如業務高峰期,自動擴容應對流量高峰
  • 熱點事件突發流量,需基於冗餘度的自動擴縮容和熱點應對機制

突發流量特徵:

Twitter推薦引擎架構設計分析

紅線流量,綠線系統承穩能力(機器數量),綠線在紅線之上方可保證系統正常執行。綠線高於紅線部分為冗餘度。

流量t1來,紅線速升,t2超過綠線,擴容系統在 t1 後某點發現流量,觸發擴容,最終機器在t3到位。

實現該突發流量擴容需做到:

  • t1~t2快速發現流量到來,如此時還未做處理,到 t2 後便已超時
  • 建立降級策略以供擴容時暫用,如停止某些次要功能、減少推薦處理條數
  • 減少擴容時間(即 t1 到 t3 的時間),最佳化程式啟動速度

具體問題可根據歷史流量資料和公司情況處理:如公司成本壓力小可將冗餘度調高,將綠線整體上移;如服務自身啟動快,可省略降級策略。

推特推薦引擎依賴已有成熟擴容基礎設施,解決流量快速發現問題;結合物料改造,引擎啟動速度從20min提高至5min。

推特推薦引擎在各環節均加入計算量條數和請求的動態降級能力,根據當前實際 QPS 與承載能力選擇降級比例。如當前可處理計算量條數的 80%,如果流量增加則只處理 70%。自動機制之外,如有熱點事件預警可全公司提前動員,每日 push 場景可提前處理。

5 總結

靈活的工具可提高開發效率。接入推特現有工具體系時,先做個可手動檢視效果及接管自動擴容邏輯的介面,提高掌控系統的速度。利用大資料類分析工具,可透過錄制大量請求、檢視其UID或某些特症等分析異常請求原因。

本次改造中大量工作為梳理舊業務程式碼,繁瑣無聊,團隊士氣也重要。推薦改造專案共歷時三個月,正確處理請求比例從不到 99%提升至 99.9%以上,服務耗時降低 25%,不增加資源支援單機 500 萬-1000 萬物料,啟動速度提升至原先的 4 倍。




來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70024924/viewspace-3008061/,如需轉載,請註明出處,否則將追究法律責任。

相關文章