快手分散式高效能圖平臺KGraph及其應用

帶你聊技術發表於2023-01-28


導讀:KGraph 是快手自 2019 年底自研的一款圖平臺,目前已經穩定應用在了社交推薦、電商推薦、安全等多個業務場景。

本文將介紹 KGraph 的系統架構,效能表現以及實際應用。主要包括以下幾大部分:

  • 背景介紹

  • KGraph 架構

  • 關鍵問題分析

  • 應用場景介紹

  • 小結與展望

分享嘉賓|張世航 快手 高階工程師

編輯整理|周思源 西安交通大學

出品社群|DataFun



01

背景介紹

1. 產品介紹


快手分散式高效能圖平臺KGraph及其應用

快手是一款國民級別的短影片 APP,同時也是領先的內容社群和社交平臺。根據快手釋出的 2022 年第一季度財報,快手社群內互相關注的使用者對數已達到了 188 億,同比漲幅接近 70%。在如此規模的使用者量級下,僅雙關的關係已達到百億級別,若再考慮快手的其他場景下的關係如使用者與影片的關係、直播電商中的點選購買關係,資料規模將非常巨大。如何儲存和利用這些關係資料是迫切要解決的重要問題。

2. 推薦

快手分散式高效能圖平臺KGraph及其應用

作為一個短影片 APP,讓影片的觀看者刷到滿意的影片以及讓釋出者的影片脫穎而出是非常重要的任務。實現該目標的方法主要是透過推薦系統。推薦系統主要包括召回和排序兩個部分,排序還可以細分為粗排、精排、重排。透過層層篩選找到使用者感興趣的影片。KGraph 主要解決召回部分所遇到的問題。

3. 社交推薦系統的痛點

快手分散式高效能圖平臺KGraph及其應用

KGraph 最早是為了解決推薦團隊的問題而誕生的。在演算法之下若能高效存取核心的基礎資料,應該能為上層最佳化留出更大的空間。在 KGraph 誕生之前,為了能高效存取資料,業務方的解決方案是儲存在記憶體圖資料結構當中。其中,記憶體圖資料結構是業務方自定義的,按照圖模型的方式載入和使用的資料。

這種方式雖然高效但依然存在幾個問題。首先是單機的記憶體限制導致圖規模的限制;其次是非持久化,每次啟動都會載入很長時間。關係型資料庫可以解決上面提到的問題但是會面臨新的問題即效能下降。推薦中依賴的多度關係的計算需要頻繁的表連線操作,導致效能低下。

因此,我們研發 KGraph,透過圖模型的多跳能力來解決效能問題。


02


KGraph 架構

1. 迅速發展的圖資料庫

快手分散式高效能圖平臺KGraph及其應用

圖資料庫指的是儲存圖資料的資料庫,其中圖資料是由節點和邊(關係)表示的資料結構。圖模型可以天然的應用在許多場景中,比如社交網路、風控領域、知識圖譜等。根據 DB-engine 的流行趨勢排名,自 2013 年 1 月到 2020 年 6 月,圖資料庫在各個型別的資料庫中漲幅最高,但是圖資料庫目前並沒有統一的查詢語言標準,比較流行的查詢語言包括 Gremlin,Cypher 和 nGQL 等。

2. 有向異構屬性圖建模

快手分散式高效能圖平臺KGraph及其應用

為了滿足不同場景的使用,KGraph 採用了有向異構屬性圖建模。其中邊是有向的,每條邊 KGraph 存了兩次,在起點處存了指向終點的出邊,在終點處存了指向起點的入邊。異構指的是點和邊包含不同的型別,比如點包含使用者型別和影片型別,每個點有對應的型別和唯一的 ID,可以透過(型別+ID)的方式查詢點。邊的型別如觀看型別,邊需要明確起點和終點,透過起點+終點+型別唯一確定一條邊。KGraph 目前只能透過查詢點的出邊或者點的入邊來找到對應的邊。屬性圖指的是點和邊上都可以附帶屬性,比如使用者點上有年齡、性別,邊上有觀看時間等資訊。相較於關係型資料庫,KGraph 中的圖對應於關聯式資料庫中的資料庫,型別對應於表,節點和邊是圖中的實體,相當於表中的一行,屬性則對應於表中的一列。

3. 整體框架

快手分散式高效能圖平臺KGraph及其應用

目前圖資料庫依賴的底層儲存主要分為兩種,一種是原生的圖儲存,另外一種是依賴於已有的 K-V 儲存或者關係型儲存。二者各有優缺,原生的儲存可以對圖模型進行專門的最佳化可以更好的提升讀寫效能;依賴已有模型的優勢是已有的儲存模型較為成熟,KGraph 則在底層儲存上選擇了後者。KGraph 的儲存層是一個自研的分散式 K-V 儲存,主要包含三個角色。首先是 DBServer,採用單程式多 Shard 的設計來提供讀寫服務並支援多 Region,多 AZ 的部署;其次是 Master,主要負責程式的管理和 Shard 的排程,Master 可以處理新程式的加入和故障程式的處理,透過排程 Shard 實現線性的擴容縮容;第三個是 KNS,是路由管理模組。

在儲存之上的是 SDK,SDK 定義了圖的模型,實現圖的基本讀寫介面;在 SDK 之上的是 GraphServer。KGraphServer 是 KGraph 系統中自研的 Proxy,對於其他語言的支援是透過 KGraphServer 來實現的。KGraphServer 還可以執行簡單的多跳過濾等計算操作。Gremlin 的底層儲存依賴 KGraph,Nebula 的底層儲存可以選擇其自帶的儲存或者是 KGraph 的 K-V 系統。在 GraphServer 之上可以搭建一些大資料平臺支援離線資料匯入或者離線的圖計算等任務。

03

關鍵問題分析

1. 社交推薦的痛點如何解決

快手分散式高效能圖平臺KGraph及其應用

KGraph 的設計主要是為了解決前面提到了兩個已有的問題即單機記憶體限制和關係型資料庫效能低下的問題。KGraph 的分散式 K-V 系統的架構設計突破了單機資料量的限制。在 KGraph 的設計中,效能被作為重點考慮,期望單臺伺服器可以達到千萬級的吞吐。搭建一個儲存服務可以簡單分為兩個部分即網路服務和持久化引擎,客戶端透過網路訪問持久化引擎,透過持久化引擎來讀寫資料並返回給客戶端。因此,高效能的網路框架和高效能的持久化引擎是迫切需要的。

2. DBServer 架構

快手分散式高效能圖平臺KGraph及其應用

首先是持久化引擎,目前應用比較廣泛的儲存硬體是 NVME SSD,可以達到百萬 IOPS(Input/Output Operations Per Second),但與期望的千萬級別還存在一定差距。因此 KGraph 在絕大多數場景採用 PMem(Persistent Memory),不僅擁有接近 DRAM 的讀寫能力還擁有持久化的能力。PMem 支援兩種使用方式,第一種是記憶體模式,直接將 PMem 當作大容量的記憶體來使用,DRAM 當作 PMem 的快取記憶體。但是該方式無法解決記憶體持久化的問題。KGraph 目前採用的是第二種使用方式即 App Direct 模式,在這種方式下將 PMem 當作磁碟來使用,透過在 PMem 上掛載 xfs 檔案系統來讀寫資料。對於線上業務,大容量低 QPS(Queries-per-second)的業務一般採用 SSD 的方案,對於高 QPS 的業務一般採用 PMem 的方案。

從實際業務來看,主要是 xfs 限制了 PMem 的吞吐。在掛載 xfs 時一般開啟 dax 選項,導致對檔案的讀寫需要直接落盤,這樣對於檔案的修改需要加鎖修改檔案的 meta 資訊。加鎖會造成瓶頸,目前仍在探索 PMem 新的使用方式。目前正在研發的是基於 PMem 的 Hash 引擎,主要的設計方案是繞過 xfs 系統,透過 PMDK 來讀寫 PMem。為了高效地定址資料,把 PMem Block 的索引結構和管理 PMem 空閒空間的 free list 儲存在 DRAM 當中,在引擎重啟時,透過掃描 PMem 重建索引,這樣 DRAM 可以快速索引資料,同時 PMem 可以高效持久化並讀寫資料。在引擎的上層引入 LRU Cache 來加速讀。針對熱點問題一般會另外架設兩級 cache 架構,採用自研的 logdb記錄 binlog,向外提供圖介面或者 K-V 介面,由 SDK 直接訪問。

從測試結果來看,基於 PMem 的 DBServer 單機讀的 QPS 能達到千萬級別。

3. 高效能 RPC 框架——KRPC

快手分散式高效能圖平臺KGraph及其應用

為了能在分散式場景下使用還需要解決網路框架問題。以單機 40 核為例,要想達到單機千萬的服務,可將問題拆解成單核 100W,如果單核 100W 要線性擴充,在設計上還需要注意執行緒衝突。單執行緒 100W,意味著留給每次 RPC 的處理時長大約為 1us,也就是 1000ns。以常見資料訪問為例,CPU 訪問 L1 Cache 的延遲是1納秒,在含有兩個節點的情況下訪問本地記憶體約80納秒,遠端記憶體訪問 140 納秒,這樣,對記憶體的解引用平均是 100 納秒。若每次RPC的處理有超過 10 次的記憶體緊引用,則單執行緒訪問小於 100 萬 QPS。為了保證單執行緒的吞吐,做了程式碼上的最佳化。從測試結果來看,每次RPC的處理時間不到 1000 納秒的延遲。

為了減少執行緒間衝突,KRPC執行緒在 RPC 處理的主流程上無鎖。在記憶體的申請和釋放方面,KRPC 使用了 tcmalloc,同一塊記憶體的申請和釋放都是由同一程式來負責的。KRPC 的架構比較簡單,主要有四層架構。最底層是網路層,主要負責管理網路連線和收發網路包。為提升效能,每次讀寫都會盡可能多的讀寫資料以減少系統呼叫的次數。訊息層主要負責接收網路層的資料並切割為上層需要的訊息,包括 RPC 訊息,Redis 訊息等。邏輯層是 RPC 框架的核心驅動層,負責處理客戶端和服務端的普通邏輯,決定訊息的處理流程。最上層為協議層,可以做多協議的擴充。目前相容的協議有 KRPC,Redis 協議,gRPC 等。KRPC 是為提高儲存系統的吞吐而研發的,具有高效能、高吞吐、低延遲、協議可擴充套件、穩定等特點。

4. 超級節點問題

快手分散式高效能圖平臺KGraph及其應用

超級節點是圖中出度非常大的一類節點,比如快手的官方賬號有十幾億的粉絲。KGraph對外提供的是圖模型但是底層依賴的是 K-V 儲存,所以需要從圖到 K-V 進行編解碼。由於點是由(Type+ID)唯一確定的,因此對點的編碼可以透過將(Type+Id)當作 Key,屬性當作 Value 來儲存。

對於邊的編解碼,需要考慮到一種情況,在實際的業務應用當中,獲取一個點的所有出邊是一個高頻操作,查詢某一條特定的邊是一種低頻的操作,所以一般有三種編解碼方案。第一種,因為起點 + 終點 + type唯一確定一條邊,所以我們可以把每條邊編碼成一個KV,這樣做的優勢是天然支援超級節點,並且讀寫一條邊,都只需要一次 IO,沒有寫放大,劣勢就是獲取出邊列表需要獲取一系列 KV,這裡可能用到 Scan,效能較差,這樣不能滿足業務高效讀出邊列表的要求,所以 KGraph,在一開始採取了第二個方案;也就是把全部出邊編碼在一個 KV 的方案,這樣做的好處就是讀出邊列表只需要一次 IO 操作,效能較好,但劣勢也很明顯,第一是寫放大比較大,寫一條邊,需要修改整個出邊列表,第二是無法解決超級節點問題,如果出邊較多,整個出邊列表編碼的 value 大小將非常大。所以,隨著這個痛點逐漸明顯,KGraph 目前也支援了第三種編碼方案,也就是把出邊列表編碼成多個 KV,並透過一定的方式管理這些 KV 的方案,KGraph 採用的是採用 BTree 的方式管理這些 KV,這種編碼可以看做上面兩種方案的折中,讀出邊列表不需要 Scan,但是需要多次 IO,支援超級節點,因為每個 Value 的邊數到達上界就會分裂,所以讀寫放大不在是第二種方案的邊的出度,變成了每個 Value 最大的閾值,這樣寫放大就變得可控。

經過測試,BTree 方案的讀出邊效能和原有方案接近,寫邊效能得到較大改善。以 20W出度的點為例,在每個 value 最多存 2000 條邊的情況下,BTree 方案的寫吞吐比原方案高出 2 個數量級,並且每個value的分裂閾值越小,寫放大越小,寫邊的吞吐越大。如果每個 value 能存 2000 條邊,2 層 BTree 就可以儲存 400W 條出邊,3 層 BTree 就能存 80 億條邊,絕大部分節點,2 層 BTree 即可解決,這樣寫一般都只需要兩次 IO。首先找到 root 節點,然後二分找到葉子節點,讀寫對應的葉子節點即可

在實際應用中,原方案和 BTree 方案可以動態轉化,在邊數小於閾值時,採取原方案,這樣保留了原方案只需要 1 次 IO 的優點,在邊數超過閾值時轉化為 BTree 方案,可以支援超級節點,調整寫放大。

5. KGraph 效能指標

快手分散式高效能圖平臺KGraph及其應用

在高效能的網路框架和儲存引擎基礎上,KGraph 的極限測試單機吞吐極限達到兩千萬QPS,並且時延較低,同機房 RPC 延遲在毫秒量級。在實際應用的過程中,單機 QPS 最高達到過 1000WQPS 以上,並且平均延遲為 600us 左右。在分散式場景下,單機的效能可以線性擴充套件並支援多 AZ 多 region 的部署。上線兩年多以來一直保持較高可用性且應用在社交推薦,電商推薦等多業務場景。

同時 KGraph 作為圖平臺,可以用多跳計算替代關係型資料庫的 join,這裡以一個簡單的測試為例。在一個 100 萬個點、每個點平均 50 出度的網路裡,找多度關係,這樣圖的規模大概是 5 千萬條邊。執行 2 跳的查詢大概需要 1.5ms,3 跳需要 40ms,4跳需要 960ms,5 跳需要 8s,4 跳的結果就幾乎訪問了全圖的點,5 條的解決結果訪問了全圖的邊,查詢時間還能控制在較低的水平。如果是關係型資料庫,在做 4 跳或者 5 跳時,可能就已經不可用。這裡還對多跳的 QPS 進行了測試,在同樣使用單臺機器的的情況下,KGraph 單機的極限吞吐表現更好,有著數量級的差距。

04

應用場景介紹

1. 基於 KGraph 實時查詢的社交推薦

快手分散式高效能圖平臺KGraph及其應用

第一個應用場景是社交推薦。作為一個社交平臺,若能在不同場景下向好友發出推薦請求,促使好友實現關注和回關可以增強好友的社交屬性,提升使用者粘性。為了計算可能認識/可能感興趣的其他使用者,這裡需要解決三個問題。第一個是龐大的資料量,在目前的使用者量級來看,按照不同的模型構圖,可能包含千億條邊或者萬億條邊,這個資料量是非常大的。第二個是吞吐較大,DAU3 億的情況下,查詢的 QPS 將會很高,要做到實時查詢也是一個挑戰。第三個是為了挖掘更多的關係,比如多度好友等等,需要對使用者之間的關係進行多度計算,需要支援這種計算能力。

如果要選擇 MySQL,大資料量可能採用分庫分表等方案,多度計算需要 join,效能會是問題。所以這裡選擇了 KGraph,KGraph 能夠支援 PB 級別資料的儲存,提供千萬 QPS 吞吐的能力,同時能夠高效的進行多度計算。

快手分散式高效能圖平臺KGraph及其應用

在叢集的使用方式上,儲存層儲存了多種線上資料和離線資料,比如可能有使用者快手站內關注,互關關係,使用者對影片的點贊,評論關係,或者是離線計算的結果比如社群計算結果。基於這些資料可以進行實時的查詢並由上層應用進行演算法計算。當前 KGraph 也正在跟業務方探索新的合作方式,將業務多跳 + 計算的邏輯下沉到圖平臺的 GraphServer,GraphServer 可以透過就近機房訪問,新增 Cache 等最佳化措施,對整體的吞吐和延遲進一步最佳化。

經過測試,不加 Cache 的情況下,單臺 GraphServer 每秒可以進行 400W 次點向量的查詢和點積計算,以 2 跳計算為例,KGraphServer的單機吞吐是 Nebula 的 2 倍多,且延遲是 nebula 的 2/3。此外,這些儲存層儲存的資料還可能作為使用者推薦的精排環節的特徵抽取,互動文案的存取等等。

2. 基於電商圖譜的推薦召回

快手分散式高效能圖平臺KGraph及其應用

其次就是電商推薦場景。

一方面,客戶投放電商廣告的目的是引導使用者對電商直播的訂閱和下單成交進而尋求 GMV 的轉化。若能精確找到有潛在購買意圖的顧客將可有效提升 GMV(Gross Merchandise Volume)。

另一方面,若使用者能快速找到想要的商品也會提升使用者的購買體驗。電商的場景,也十分適合 KGraph 的圖模型。在 KGraph 儲存層,儲存了電商圖譜的各種物件,可能包括使用者、店鋪、商品、直播、影片等,也構建了物件之間的各種複雜關係,比如可能有使用者之間網紅家族關係,影片對直播的預熱關係,店鋪和商品之間的關係等等。基於這些資料,可以進行實時的推薦召回,比如可能有標籤召回,根據 KGraph 的電商圖譜的資料,透過模型計算,篩選出優質廣告,作為召回結果;再比如可能有上架商品實時召回,可能根據使用者最近瀏覽過商品的類目等資訊,拉取正在上架同樣類目的直播廣告進行精準匹配,最終返回直播廣告佇列,還可能有品牌召回等多種召回策略。除此之外,還可以在這些資料上進行離線的特徵計算和儲存,有了電商圖譜,未來還可以進行更多策略的挖掘。

3. 利用 Spark 的離線圖計算

快手分散式高效能圖平臺KGraph及其應用

KGraph也支援離線的圖計算任務,在 KGraph 的儲存之上也支援 Nebula 的查詢引擎。在上層還可以使用 Spark,利用 SDK 或者 Nebula 讀寫 KGraph 的資料執行一些複雜的圖演算法,比如 k 跳子圖或者最短路徑,並把結果寫回 KGrpah 或者寫到 Hive 中。

05

小結與展望

快手分散式高效能圖平臺KGraph及其應用

KGraph 最突出的優勢是效能優勢。憑藉 PMem 和高效能網路框架 KRPC,能達到單機千萬的極限吞吐和低延遲,為上層最佳化留出更多空間。KGraph 目前支援 OLTP 的實時查詢和 OLAP 計算,已經穩定應用在快手社交推薦和電商推薦等場景。KGraph 目前處在快速發展的階段,使用者規模和叢集規模都在不斷擴大。展望一下 KGraph 後續的發展,一方面需要系統更加完善,雖然已經對接了 Nebula 查詢引擎,但他的查詢效能目前還無法滿足很多線上查詢的要求,我們期望自研圖查詢引擎,解決 SDK 語義簡單的問題。同時還要支援多種圖儲存底座,比如團隊內部自研的儲存底座。另外 KGraph 目前還偏向圖儲存,將來也會更多的做圖計算圖學習的探索。

隨著叢集規模的增大,叢集的維護已經成為一項很重要的工作。所以,叢集的高可用,易維護也是我們關注的重點。另外,除了目前的應用場景以外,也在積極的探索更多的應用場景,比如知識圖譜,安全風控等場景。



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

相關文章