动态

详情 返回 返回

得物自研DGraph4.0推薦核心引擎升級之路 - 动态 详情

一、前言

DGraph是得物自主研發的新一代推薦系統核心引擎,基於C++語言構建,自2021年啓動以來,經過持續迭代已全面支撐得物社區內容分發、電商交易等核心業務的推薦場景。DGraph在推薦鏈路中主要承擔數據海選和粗排序功能,為上層精排提供高質量候選集。

核心技術特性:

  • 索引層 - 支持KV(鍵值)、KVV(鍵-多值)、INVERT(倒排)、DENSE-KV(稠密鍵值)等。索引存儲支持磁盤 & 內存兩種模式,在預發等延遲壓力低場景,通過磁盤索引使用低規格服務器提供基本服務。線上場景使用內存索引保證服務穩定性,提供毫秒級延遲響應。索引更新支持雙buff熱更新【內存足夠】、服務下線滾動更新【內存受限】、Kafka流式數據實時更新等三種模式。
  • 查詢層 - 支持向量檢索IVF & HNSW、鍵值(KV)查詢、倒排檢索、X2I關聯查詢、圖查詢。對外提供JavaSDK & C++ SDK。

系統依賴架構:

  • 索引全生命週期管理由得物索引平台DIP統一管控。
  • 服務發現基於ZooKeeper(zk)。
  • 集羣資源調度基於得物容器平台,目前已經支持HPA。

服務規模:

目前在線100+集羣,2024年雙11在線突破了100W QPS。

本文主要介紹DGraph系統在2024年的一些重要改進點。主要包括兩次架構調整 + 性能優化 + 用户體驗提升方面的一些工作。

二、架構升級

2.1 垂直拆分業務集羣支持

在2023年前,DGraph系統始終採用單一集羣架構提供服務。該架構模式在平台發展初期展現出良好的經濟性和運維便利性,但隨着業務規模擴張,單集羣架構在系統層面逐漸顯露出三重剛性約束:

  1. 存儲容量瓶頸 - 單節點內存上限導致數據規模受限;
  2. 網絡帶寬瓶頸 - 單物理機Pod共享10Gbps帶寬,實際可用帶寬持續承壓,推薦引擎業務中部分核心集羣200餘張數據表(單表需20分鐘級更新)的實時處理需求已遭遇傳輸瓶頸;
  3. 計算能力瓶頸 - 單實例最大64核的算力天花板,難以支撐複雜策略的快速迭代,核心場景響應時效與算法複雜度形成顯著衝突;
  4. 穩定性 - 大規格集羣對於容器調度平台不友好,在擴容、集羣故障、集羣發佈時耗時較久;基於得物平台推薦數據量增長和算法迭代需求,我們實施業務垂直拆分的多集羣架構升級,通過資源解耦與負載分離,有效突破了單節點資源約束,為複雜算法策略的部署預留出充足的技術演進空間。

系統改進點是在DGraph中增加了訪問了其他DGraph集羣 & FeatureStore特徵集羣的能力(圖1)。為了成本考慮,我們複用了之前系統的傳輸協議flatbuffers,服務發現仍基於ZooKeeper。

圖 1 DGraph 訪問架構改進

改造的難點在圖化集羣!

目前推薦業務的核心場景都進行了圖化改造,圖化查詢是把多路召回、打散、融合、粗排等策略打包到一個DAG圖中一次發送到DGraph,DGraph的算子調度模塊根據DAG的描述查詢索引數據 & 執行算子最終把結果返回給業務系統,但這些DAG圖規模都很大,部分業務DAG圖涉及300+算子,因此如何在垂直拆分業務中把這些DAG圖拆分到不同的DGraph集羣中是一個非常複雜的問題,我們主要做了三方面改進:

  1. DAG管理 - 集羣分主集羣和從集羣【多個】,DAG圖部署在存在主集羣中,DIP平台會分析DAG的拓步結構並把屬於從集羣的部分複製出來分發給從集羣,為了保證DAG的一致性,只允許從主集羣修改DAG圖;
  2. 集羣劃分 - 通常按召回劃分,比如Embedding召回、X2I召回、實驗召回可以分別部署在不同的集羣,另外也可以把粗排等算力需求大的部分單獨放在一個集羣,具體根據業務場景調整;
  3. 性能優化 - 核心表多個集羣存放,減少主集羣和從集羣間數據交換量。


圖 2 DGraph業務垂直拆分集羣

2.2 分佈式能力支持

垂直拆分集羣,雖然把推薦N路召回分散到了M個集羣,但是每個集羣中每個表依然是全量。隨着得物業務的發展,擴類目、擴商品,部分業務單表的數據量級已經接近單集羣的存儲瓶頸。因此需要DGraph中引入數據水平拆分的能力。


圖 3 DGraph 分佈式集羣架構圖

在DGraph分佈式架構設計中,重點考慮了部署成本優化與業務遷移工作量:

  1. 分佈式集羣採用【分片數2】×【雙活節點2】×【數據副本數2】的最小拓撲結構,理論上需要8台物理節點保障滾動更新與異常容災時的穩定性。針對CPU負載較輕的場景,為避免獨立Proxy集羣帶來的額外資源開銷,DGraph將Proxy模塊和DGraph引擎以對稱架構部署到所有節點,通過本地優先的智能路由策略(本地節點輪詢優先於跨節點訪問)實現資源利用率與訪問效率的平衡;
  2. 在業務兼容性方面,基礎查詢接口(KV檢索、倒排索引、X2I關聯查詢)保持完全兼容以降低遷移成本,而DAG圖查詢需業務側在查詢鏈路中明確指定Proxy聚合算子的位置以發揮分佈式性能優勢。數據鏈路層面,通過DIP平台實現索引無縫適配,支持DataWorks原有任務無需改造即可對接分佈式集羣,同時增量處理模塊內置分片過濾機制,可直接複用現有Flink實時計算集羣進行數據同步。

三、性能優化

3.1 算子執行框架優化

在DGraph中,基於DGraph DAG圖(參考圖9)的一次查詢就是圖查詢,內部簡稱graphSearch。在一個DAG圖中,每個節點都是一個算子(簡稱Op),算子通過有向邊連接其他算子,構成一個有向無環圖,算子執行引擎按DAG描述的關係選擇串行或者併發執行所有算子,通過組合不同算子DAG圖能在推薦場景中靈活高效的完成各種複雜任務。

在實際應用場景中受DAG圖規模 & 超時時間(需要控制在100ms內)限制,算子執行框架的效率非常重要。在最開始的版本中我們使用過Omp & 單隊列線程池,集羣在CPU負載低於30%時表現尚可,但在集羣CPU負載超過30%後,rt99表現糟糕。在降本增效的背景下,我們重點對算子執行框架進行了優化,引入了更高效的線程池 & 減少了調度過程中鎖的使用。優化後目前DGraph 在CPU壓力超過60%依然可以提供穩定服務。


圖4 DGraph算子執行框架優化

線程池優化:將原1:N 的線程池-隊列架構調整為M:N 分組模式。具體實現為將N個工作線程劃分為M個執行組(每組N/M線程),各組配備獨立任務隊列。任務提交採用輪詢分發機制至對應組隊列,通過資源分區有效降低線程調度時的鎖競爭強度。

調度器優化:在DAG調度過程中存在兩個典型多寫場景

  1. 前驅算子節點完成時需並行更新後繼節點標記;
  2. DAG全局任務計數器歸零判斷。原方案通過全局鎖(Graph鎖+Node鎖)保障原子性,但在高負載場景引發顯著鎖競爭開銷,影響線程執行效率。經分析發現這兩個狀態變更操作符合特定併發模式:所有寫操作均為單調增減操作,因此可將鎖機制替換為原子變量操作。針對狀態標記和任務計數場景,分別採用原子變量的FetchAdd和FetchSub指令即可實現無鎖化同步,無需引入CAS機制即滿足線程安全要求。

3.2 傳輸協議編碼解碼優化

優化JavaSDK - DGraph數據傳輸過程:在DGraph部分場景,由於請求引擎返回的數據量很大,解碼編碼耗時佔整個請求20%以上。分析已有的解碼編碼模塊,引擎在編碼階段會把待傳輸數據編碼到一個FlatBuffer中,然後通過RPC協議發送到業務側的JavaSDK,SDK解碼FlatBuffer封裝成List<map> 返回給業務代碼,業務代碼再把List<map> 轉化成 List<業務Object>。過程中沒有併發 & SDK側多了一層冗餘轉換。

優化方案如下: 

  1. 串行編碼調整為根據文檔數量動態調整編碼塊數量。各子編碼塊可以併發編碼解碼,加快編碼&解碼速度,提升整體傳輸性能;
  2. SDK側由 Doc -> Map -> JavaObject 的轉化方式調整為 Doc -> JavaObject,減少解碼端算力開銷。


圖5 DGraph 傳輸編碼解碼過程優化

四、用户體驗優化

4.1 DAG圖調試功能優化

目前我們已經把DGraph DAG圖查詢的調試能力集成到DIP平台。其原理是:DGraph 的算子基類實現了執行結果輸出,由於算子的中間結果數據量極大,當調試模塊發現調試標誌後會先把當前算子的中間結果寫入日誌中,數據按TraceID + DAGID+ NodeID 組織,最終這些數據被採集到SLS日誌平台。


圖6 DGraph DAG圖查詢調試

從DIP平台調試DAG圖請求,首先通過DGraph JavaSDK的調試入口拿到DAG圖請求json,填入DIP平台圖請求調試入口,發起請求。索引平台會根據請求體自動關聯DAG圖並結合最終執行結果通過頁面的方式展示。DIP平台拿到結果後,在DAG圖中成功的算子節點標記為綠色,失敗的節點標記為紅色(圖6)。點擊任意節點可以跳轉到日誌平台查看該節點的中間結果輸出。可用於分析DAG圖執行過程中的各種細節,提升業務排查業務問題效率。

4.2 DAG圖支持TimeLine分析

基於Chrome瀏覽器中的TimeLine構建,用於DGraph DAG圖查詢時算子性能分析優化工作。TimeLine功能集成在算子基類中,啓動時會記錄每個算子的啓動時間、等待時間、完成時間、執行線程pid等信息,這些信息首先輸出到日誌,然後被SLS日誌平台採集。用户可以使用查詢時的TraceID在日誌平台搜索相關的TimeLine信息。

圖7 DGraph DAG圖例子

圖8 使用瀏覽器查看DGraph DAG圖 TimeLine

當我們拿到請求的TimeLine信息後,通過瀏覽器加載可以通過圖形化的方式分析DAG執行過程中耗時分佈。圖7是一個DAG 請求,它有9個算子節點,圖8是它的一次請求的TimeLine。通過分析這些算子的耗時,可以幫助我們定位當前DAG圖查詢的瓶頸點在哪裏,從而精準去解決性能方面的問題。

4.3 DAG圖支持動態子圖

在DAG圖召回中,業務的召回通常都帶有一些固定模式,比如一個業務在一個DAG圖召回中有N路召回,每一路召回都是:① 查找數據;② 關聯可推池;③ 打散; 它們之間的區別可能僅僅是召回數據表名不同或者傳遞的參數不同。通常我們業務調整或者算法實驗調整隻需要增加或者減少部分召回,原有模式下這些操作需要去新增或者修改DAG圖,加上算法實驗很多,業務維護DAG圖的成本會非常高。

DAG動態子圖的引入就是為了解決這類問題,首先我們在DAG圖中配置一個模板子圖,它僅僅描述一個行為模式,代表會涉及幾個算子,算子之間的關係如何,實際的參數以及召回路的數量則由業務方在發起請求時動態決定。子圖的執行和主圖的執行共用同一套調度框架,共享運行時資源以降低運行開銷。

圖9 DGraph 子圖

圖9是一個DAG召回使用DAG子圖後的變化,它有8路召回,一個Merge節點,這些召回分為兩類,一類是基於KV表(ForwardSearch)觸發的向量召回,另外一類是基於KVV表(IvtSearch)觸發的向量召回。引入DAG子圖後,在主圖中節點數量由17個降為3個。

五、展望未來

過去四年,DGraph聚焦於實現得物推薦引擎體系從0到1的突破,重點完成了核心系統架構搭建、算法策略支持及業務迭代空間拓展,取得多項基礎性成果。基於2024年底的用户調研反饋結合DGraph當前的發展,後續將重點提升產品易用性、開發與運維效能及用户體驗,同時在系統穩定性、可擴展架構和平台化建設方面持續深化。

文 / 尋風

關注得物技術,每週一、三更新技術乾貨

要是覺得文章對你有幫助的話,歡迎評論轉發點贊~

未經得物技術許可嚴禁轉載,否則依法追究法律責任。

user avatar u_16776161 头像 banana_god 头像 lenglingx 头像 rivers_chaitin 头像 lvlaotou 头像 hankin_liu 头像 haixiudezhusun 头像 ailvyoudetiebanshao 头像 liuyue_5e7eb6745e089 头像 infinilabs 头像 evilboy 头像 lvweifu 头像
点赞 28 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.