社交搜索Graph Search技術解析

  Facebook是目前世界上最著名的社交網站,月活躍用戶已超過10億,每日登陸網站的用戶超過6億。如果從數據抽象的角度來看,Facebook的社交圖不僅包括好友之間的關係,還包括人和實體以及實體之間的關係,每個用戶,每個頁面,每張圖片,每個應用,每個地點以及每個評論都可以作爲獨立實體,用戶喜歡某個頁面則建立了用戶和頁面之間的關係,用戶在某個地點簽到則建立了用戶和地點之間的關係……如果將每個實體看作圖中的節點,實體之間的關係看作是圖中的有向邊,則Facebook的所有數據會構成超過千億條邊的巨量實體圖(Entity Graph)。實體圖中的關係有些是雙向的,比如朋友關係,有些則是單向的,比如用戶在某個地點簽到。同時實體還具有自己的屬性,比如某個用戶畢業於斯坦福大學,出生於1988年等,這些都是用戶實體的屬性。圖1是Facebook實體圖的一個示意片段。

 

                                          圖1 Facebook實體圖(Fbid是Facebook內部唯一ID編號)

對這個巨大實體圖的搜索需求可以分爲兩類,一類是對於某類實體的搜索,常見的需求是根據實體名稱搜索具體實體,實體圖中的用戶,圖片,應用,地點等都可以成爲被搜索的對象,比如搜索者搜索“Jordan”,搜索系統將所有名字裏包含Jordan的其它用戶搜索出來;另外一類搜索需求涉及到實體之間的關係,比如“Jordan都有哪些朋友”。

GraphSearch的定位就是成爲能夠讓用戶採用自然語言界面既能夠搜索實體,也能夠搜索實體關係的社交搜索引擎。這裏需要強調的是:Graph Search不僅僅是傳統的關鍵詞搜索,還允許用戶用自然語言來對結果進行搜索,即用戶可以直接提問:”Facebook有哪些員工是華人”,而其可以通過自然語言處理技術理解用戶真正想搜的內容,並給出精準的搜索結果。使用Graph Search,可以在這個巨量實體圖上搜索類似以下複雜的自然語言查詢:

a.Facebook的員工喜歡的餐館有哪些;

b.畢業於斯坦福大學的人都喜歡看什麼電影;

c.我的朋友喜歡去的旅遊景點有哪些;

 

Facebook Graph Search是如何做到這一點的呢?爲了理解其內部運行機制, 需要先了解Graph Search的倒排索引服務Unicorn系統。

 

Unicorn:Graph Search的基石

倒排索引是搜索引擎最重要的基礎構件之一。對於通用的網頁搜索引擎比如百度谷歌來說,倒排索引的功能是建立單詞到出現過這個單詞的網頁列表之間的映射關係,這樣,當用戶輸入某個查詢詞,搜索系統通過倒排索引找到出現過這個搜索詞對應的網頁列表,並按照若干排序因子對搜索結果排序,這樣就完成了一次搜索過程。

Unicorn是建立在具有接近百億節點的實體圖上的倒排索引服務架構。與一般的網頁搜索倒排索引不同,Unicorn具有幾個獨特的特性和挑戰:

1.        不僅要對實體名稱、評論內容等傳統的文本內容進行索引,還需要對社交關係(朋友關係)用戶行爲(用戶標記某個頁面爲liked)等建立索引。這裏面臨的技術挑戰是:如何將社交關係這種涉及多實體關係的數據存入索引結構?

2.        爲了能夠快速響應用戶查詢,Unicorn會將幾十億節點以及千億以上的邊信息對應的索引結構保存在服務器內存中。傳統的搜索引擎儘管也需要處理百億級別的網頁數據,但是索引結構往往是存儲在磁盤中,通過外存索引加內存Cache的模式來加快查找速度。對於全內存的存儲方式,如何設計整體架構來保存這種海量信息是非常有技術難度的。

3.        爲了能夠支持類似“Facebook的員工都喜歡什麼餐館”這種複雜查詢,Unicorn定義了一套獨具特色的集合操作符,通過操作符的嵌套與組合,不僅可以支持類似的複雜查詢,還可以兼顧搜索的社交屬性及搜索結果的多樣性。

 

下面將從Unicorn的數據模型、整體架構及其定義的獨具特色的集合操作符來講解Facebook的技術人員是如何應對這些技術挑戰的。

 

Unicorn的數據模型

 

                                                圖2. 社交關係倒排列表與內容倒排列表

 

作爲實體圖的倒排索引,Unicorn與常見的倒排索引有一定差異。通常的倒排索引由所有網頁中出現的單詞項Term及其對應的倒排列表(Posting List)構成。倒排列表往往由一系列倒排列表項(Posting)構成,每個倒排列表項包含網頁ID,單詞在網頁中出現的次數以及單詞在網頁中出現的位置信息等構成。

 Unicorn的倒排索引與傳統倒排索引有三個主要不同點(參考圖2):

首先,Unicorn的單詞項不僅僅包含了傳統的單詞,也將社交關係或者用戶行爲引入。爲了表達節點之間的關係,可以構造<edge-type>:<ID>作爲單詞項來表達某個節點通過社交形成的邊或者用戶行爲邊,這裏<edge-type>代表了邊的類型,<ID>代表了節點的內部唯一編號,比如friend:5作爲單詞項的含義是節點5的朋友關係,而likes:5則代表了節點5喜歡哪些頁面這種用戶行爲。

其次,倒排列表中的倒排列表項(Posting)包含的內容也與傳統倒排列表有很大差異。Unicorn的倒排列表項由(DocID,HitData)構成,其中DocID又由(Sort-Key,ID)兩項元素組成。Sort-Key是整型數值,代表了這個索引項的全局重要性,倒排列表項按照Sort-Key大小降序排列,最重要的項目排在前列,這樣有利於搜索時採取截斷等操作來快速找到優質的滿足搜索條件內容。如果兩個索引項Sort-Key相同,則按照ID值由小到大升序排列。HitData保存的數據與具體應用相關,不同的應用可能會在這裏存儲不同的數據。HitData常見的應用場景是對搜索結果進行進一步的過濾,比如圖2中所示的例子,單詞項“MIT”中的倒排列表中列出了畢業於麻省理工學院的圖節點ID列表,而對應的HitData中則存儲了每個畢業於麻省理工人員對應的畢業日期和專業信息,這樣可以對搜索結果進行進一步的過濾,比如可以指定畢業於計算機專業(CS)的MIT畢業生等複雜查詢。

另外,Unicorn的特點是將所有倒排索引信息都存儲在服務器內存中。這樣可以快速響應用戶查詢,但是考慮到實體圖數量以億計,非常巨大,單機的內存遠遠沒有足夠資源對其進行存儲,必然採取分佈式集羣的方式來對索引數據進行管理,至於如何對如此海量數據進行高效管理,本文的整體架構小節會對此有講解。

上述內容描述了Unicorn的倒排索引數據模型,除此外,Unicorn還需要維護社交圖節點的正向索引(Forward Index)。所謂正向索引,就是以(key,value)形式存在的數據,其中key是圖節點的ID,value則會存儲圖節點的一些屬性信息,這些信息可以用來對搜索結果內容展示或者進行一些條件過濾。

 

 

 Unicorn的整體架構

 

                                                                 圖3  Unicorn整體架構圖

 

 

Unicorn的整體架構分爲樹狀的四層結構(圖3):頂層聚集器,垂直聚集器,RACK聚集器以及索引服務器。頂層聚集器負責接收用戶查詢並根據搜索結果類型將查詢分發到對應的垂直聚集器中(比如搜索結果是“用戶“類型,則分發給”用戶“類型垂直聚集器),同時從垂直聚集器接收返回結果做些優選返回給用戶。垂直聚集器從頂層聚集器接收用戶查詢,並將查詢分發到RACK聚集器。RACK聚集器同樣將查詢分發給RACK內所有索引服務器併合並截斷索引服務器返回的結果,RACK聚集器的優勢在於同一機櫃內服務器通信效率高。索引服務器負責在內存維護社交圖部分數據(Shard)的倒排索引,同時索引服務器負責and/or等集合操作來獲得本部分數據的搜索結果,一般一個索引服務器能夠索引幾十億條倒排列表信息。

不同垂直聚集器包含的RACK數量有很大差異,這是由該種類型數據在實體圖中的數量決定的,比如“用戶”類型的圖節點以十億計數,所以必然需要較多數量的機器,而“應用”類型的數據相比之下所需資源會少很多。

考慮到數據的可用性,Unicorn以垂直聚集器爲單位進行數據冗餘備份。如果某個索引服務器負責的數據發生故障,RACK聚集器負責將相應的請求轉發到其它垂直聚集器裏對應的備份數據中。

 

Unicorn的查詢語言

爲了能夠支持複雜的應用查詢邏輯,Unicorn定義了一些集合操作符,查詢語言通過組合這些查詢操作符可以表達複雜查詢邏輯。

最常用和最簡潔的操作符是Term操作符,其含義是直接讀取某個Term的倒排列表,比如(Term friend:5)代表的語義是找出fbid爲5的節點的所有朋友關係;

常見的集合操作符還包括And/Or/Difference操作,分別代表對兩個集合的交集、並集及差集運算。比如(andfriend:5 friend:6)代表找出同時是節點5和節點6朋友的人員集合;(or friend:5 friend 6)代表找出節點5的朋友或者節點6的朋友集合;(difference friend:5 friend:6)代表找出是節點5的朋友而不是節點6的朋友集合。

除了上面提及的常見集合操作符號外,Unicorn另外定義了三個獨具特色的集合操作符:Weak-And/Strong-Or/Apply。

 

Weak-And操作符

爲了增加搜索結果排序的社交化效果,可以考慮將搜索結果限定在發出搜索查詢詞用戶的朋友圈內。比如用戶Jones(假設該用戶內部Fbid=3)發出查詢“Mark”,不考慮社交因素的方式可以直接將名字裏包含Mark的用戶列表找出(即查詢:(Term Mark));如果考慮社交因素,可以將搜索結果範圍限定在搜索者Jone的朋友圈內(即查詢:(And Mark friend:3))。

但是如果所有查詢都這樣操作也會帶來相應的問題:搜索範圍限制得過於死板和嚴格。如果嚴格按照上述邏輯,可能存在質量較好的搜索結果,但其不在搜索用戶的朋友圈內,這樣就將這種高質量的搜索結果排除在外了。爲了解決上述矛盾,Unicorn引入了Weak-And操作符,顧名思義,這是對And操作符的一種弱化和條件放鬆。Weak-And允許一定比例或者個數的搜索結果不需要滿足所有條件也可以進入最終搜索結果隊列。

 

                                                 圖 4.  Weak-and操作符

假設當前用戶Jones(fbid=3)搜索“manlanie mars”,圖4是內存中對應這個搜索的索引結構。如果Graph Search在內部施加了Weak-and操作符,其對應的內部查詢語言爲:(weak-and (termfriend:3 :optional-hits 2) (termmanlanie)(term mars))。對應這條查詢語言,Graph Search返回給用戶的結果是ID列表:15,20,7,57,其中,7和57屬於同時滿足三個條件的結果,而因爲weak-and指出了friend:3的optional-hits條件爲2,意思是結果中最多允許2個結果不在Jones的朋友圈中,Sort-Key較高的15和20不在Jones的朋友圈中,已經將這兩個指標占滿,所以75這個結果就不再展示給用戶。Weak-and除了可以採用指定個數外,還可以用optional-weight的方式按照結果比例指定結果分佈。

 

Strong-Or操作符

與Weak-And操作符相對應,Unicorn提出了針對Or操作符的改進Strong-Or操作符。這個操作符強制規定:滿足某些搜索條件的搜索結果數目必須達到總體結果的指定比例。比如下面的例子:

(stong-or friend:3

           (and friend:3 live-in:100 :optional-weight 0.2)

           (and friend:3 live-in:101 :optional-weight 0.3) )

其語義代表了查找Jones的朋友,同時要求其中至少20%的朋友居住在北京(fbid=100),至少30%的朋友居住在洛杉磯(fbid=101)。至於其他50%的結果對其居住地不做任何限制。 通過這種方式可以採用靈活的方式強制搜索結果增加多樣性。

 

Apply操作符

因爲Facebook的所有信息構成了巨大的實體圖,很多實際應用會有順着圖中節點沿着邊進行遊走遍歷的操作。對於一度關係遍歷,Unicorn已經通過索引將其建立到索引信息中,可以一次讀取直接獲得,但是對於二度遍歷甚至更高度的遍歷,則無法直接從索引中一次性讀出。

假設某個用戶希望找到:Jones的朋友喜歡哪些頁面,這是一個典型的社交圖上的二度遍歷操作。一個很直接的解決方案如下:首先可以構造查詢,找出Jones的朋友,即(friend:3 ),假設結果是fbid爲5和6的人,Unicorn的頂層聚集器在接收到這個搜索結果後,構造另外一個查詢就可以找出這些人喜歡的頁面,即(or likes:5 likes:6)。這樣,一個二度遍歷操作可以轉化爲分別由and和or連續的兩次查詢來解決問題。

Apply就是直接使用單個表達符號來完成上述邏輯的操作符。如果一個二度遍歷可以由第一步的and操作符,以及對第一步的搜索結果採用or操作符來構造,那麼就可以使用Apply操作一步到位。比如上面的例子就可以用:(Apply likes:friend:3)來完成。

 

Graph Search

  

如何建立索引

      Graph Search具有兩種不同類型的索引建立通道,一條通道是批處理類型的,一次處理大批量待索引的數據;另外一條通道是爲了保證信息更新的時效性而建立的接近實時的索引更新通道。

批處理索引通道的原始數據存儲在數據庫中,通過Hive可以對這些數據進行訪問。在建立索引的時候,只需要程序員寫少量代碼將Hive中的每行數據轉換爲(term,sort-key,id,HitData)這種格式,系統提供了Hadoop例程來自動將這種格式的數據轉換爲Unicorn的索引,並將其拷貝到對應的索引服務器中。

近實時索引通道通過Scribe來作爲連接更新數據和索引的聯繫通道。當實體圖數據發生變化時,將這種數據變化寫入Scribe系統,然後Scribe系統會以Thrift客戶端形式將變化的數據寫入索引系統。

 

   搜索過程

用戶利用GraphSearch完成一次完整的搜索涉及兩個連續的過程:搜索建議階段和搜索階段。當用戶輸入查詢內容時,GraphSearch會通過自然語言處理模塊試圖理解用戶的搜索意圖並給出若干搜索建議,當用戶點擊某個搜索建議後,系統進行真正的搜索並將搜索結果返回給用戶。

在搜索建議階段,自然語言處理模塊試圖將用戶當前輸入通過句法分析構建一顆句法樹,同時這個模塊將用戶輸入中的某些片段識別爲可能的實體類型(地點,人名等),並將這些片段提交Unicorn系統,同時根據Unicorn的搜索結果來構建各種可能的句法分析樹,並賦予每個句法分析樹不同權重,然後選擇得分較高的句法分析結果作爲提示用戶的內容。比如用戶輸入“friends at Facebook”,自然語言處理模塊會建議:Friends whowork at Facebook,以此作爲猜測的用戶搜索意圖。

當用戶選擇了某個搜索建議進行搜索時,Graph Search將對應的句法樹和在上一階段搜索獲得的實體內部ID提交給Unicorn的頂層聚集器,自然語言解析的結果以用戶可讀的方式展示在對應的搜索URL中,比如用戶搜索:restaurants liked by Facebook employees,其對應的URL包含:

273819889375819/places/20531316728/employees/places-liked/intersect

這裏的273819889375819是系統內部中“餐館”對應的類別ID,20531316728是“Facebook”實體對應的內部ID,這個URL已經能夠在一定程度上以內部操作符的方式代表用戶的搜索意圖:求餐館類型的地點實體和facebook員工喜歡的地點實體的交集。

當頂層聚集器收到上述URL,可以形成一個查詢規劃:首先在某個垂直聚集器進行查詢,根據查詢結果構建新的內部查詢語言,將其提交給另外一個垂直聚集器,以此類推可以序列執行一系列查詢並得到最終結果。以上面的例子來說明,首先向“用戶”這個類別的垂直聚集器提交查詢(term employee:20531316728),即查找Facebook的員工信息列表,假設返回n個結果fbid1,fbid2…..fbidn,那麼形成新的查詢:(andplace-kind:273819889375819 (or liked-by:fbid1 liked-by:fbid2 ... liked-by:fbidn)),並提交給“地點”類型的垂直聚集器,返回的結果就是用戶希望獲得的搜索結果。結合上文提到的Unicorn整體架構圖,我們可以梳理出上述查詢的整個執行流程如下:

Step 1:句法分析樹及對應實體ID提交給頂層聚集器,聚集器形成查詢規劃;

    Step 2:爲“用戶”類型的垂直聚集器準備好查詢:(term employee:20531316728)

    Step 3:頂層聚集器有時會根據用戶個人信息改寫上述查詢,主要是加入社交因素並通過weak-and或者Strong-or來保證社交因素起作用的同時也能一定程度上保證搜索結果的多樣性;

   Step 4:”用戶“類型垂直聚集器接收到查詢並將其通過RACK聚集器分發給所有索引服務器;

   Step 5:每個索引服務器從自己維護的索引中檢索出部分用戶實體的結果,對結果打分排序並將得分較高的部分用戶實體返回給“用戶“類型垂直聚集器;

   Step 6:垂直聚集器收集各個索引服務器傳回的結果並將其返回給頂層聚集器;

   Step 7:頂層聚集器根據返回的結果fbid1,fbid2……fbidn,爲“地點”類型垂直聚集器形成新的查詢:(and place-kind:273819889375819 (orliked-by:fbid1 liked-by:fbid2 ... liked- by:fbidn)),並將其發送給“地點”垂直聚集器;

   Step 8:“地點”垂直聚集器將接受到的查詢通過RACK聚集器分發給所有索引服務器;

   Step 9:索引服務器在自己維護的索引裏搜索結果並將得分較高的地點實體返回給“地點”垂直聚集器;

  Step 10:”地點“垂直聚集器接收各個索引服務器的返回結果,合併後提交給頂層聚集器;

  Step 11:頂層聚集器對結果進行重新打分並將得分較高結果返回給用戶作爲搜索結果。

 

從以上查詢的執行流程,可以看出整體架構圖中各個構件的具體功能及其流程關係。

 

搜索結果排序

對於搜索引擎來說,搜索結果排序質量好壞直接關係到用戶體驗,對於網頁搜索來說,最主要的兩個排序因素是內容相關性以及通過網頁之間的鏈接關係分析得出的網頁重要性排名,除此外還會融合查詢詞出現位置等很多其它因素來最終人工擬合抑或通過機器學習算法來自動推導出搜索結果排序公式。

GraphSearch採用了簡單的機器學習框架來對搜索結果進行排序,即採用對若干影響搜索排名的因子進行線性加權來計算獲得最終搜索結果排名,而影響排名的因子包括:搜索用戶和搜索結果地理位置的距離遠近;搜索用戶和搜索結果通過朋友關係推導出的親密程度;查詢串和搜索結果字符串的重疊程度等幾十種排序特徵。Facebook工程師認爲這種簡單的機器學習排序框架有利於整個系統的可理解性和可維護性。

除了上述簡單機器學習框架外,Graph Search系統非常關注搜索結果的多樣性(Diversity)。Unicorn本身提供的Wenk-And 和Srong-Or是保證搜索結果多樣性的一種措施,除此外,Unicorn提供了對於同一類查詢結果同時採納多種不同側重點的打分函數機制,這樣每個搜索結果會同時得到多個不同維度的得分,在排序的時候可以考慮採用一定策略來融合不同打分函數的結果,以此來保證搜索結果的多樣性。比如對於搜索附近地理位置的查詢(Nearby),可以提供三種不同類型的打分函數,一種考慮搜索結果的熱門程度,一種考慮搜索用戶的社交關係,還有一種考慮距離遠近。這樣每個搜索結果會附帶三個不同的得分,在排序時爲了保證結果的多樣性,可以按照一定比例將三種高得分結果進行混合輸出。

 

 

結束語

      社交化是當前很多互聯網應用的發展趨勢,而社交化數據往往比較適合採用實體圖來建立數據模型。面對海量的實體圖數據,如何構建其上的搜索系統,使得這個搜索系統能夠回答各種涉及關係類型的複雜查詢,這都是社交化互聯網應用必須解決的技術問題。Facebook作爲世界最大的社交網站,通過Graph Search爲我們提供了一套行之有效的解決方案,本文對這套技術方案進行了技術講解,期望國內同仁
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章