一種面向大規(guī)模社交網(wǎng)絡(luò)的圖數(shù)據(jù)存儲及查詢方法
【技術(shù)領(lǐng)域】
[0001]本發(fā)明涉及一種面向大規(guī)模社交網(wǎng)絡(luò)的圖數(shù)據(jù)存儲及查詢方法,屬于軟件技術(shù)領(lǐng)域。
【背景技術(shù)】
[0002]目前,圖數(shù)據(jù)存儲的主流做法是將圖數(shù)據(jù)經(jīng)過預(yù)處理,轉(zhuǎn)化為邊和頂點的記錄,以順序數(shù)據(jù)集的形式存儲在分布式文件系統(tǒng)的大文件中。訪問圖數(shù)據(jù)時,以順序掃描的方式訪問存儲圖數(shù)據(jù)的大文件。該組織方式無法為多輪迭代的圖計算應(yīng)用提供有效的數(shù)據(jù)存儲和訪問性能,為了提高圖數(shù)據(jù)的訪問性能,圖數(shù)據(jù)的內(nèi)存管理技術(shù)成為了一個重要的趨勢,如 Trinity,Giraph 等。
[0003]Neo4j是采用Key-Value存儲模型的圖數(shù)據(jù)庫,最基本的存儲單位是頂點和邊,當(dāng)廣度遍歷BFS時,獲取某一頂點鄰域操作的性能明顯比以頂點鄰域作為基本存儲單位的系統(tǒng)要低。Neo4j所有的數(shù)據(jù)存儲在磁盤上,采用內(nèi)存緩存加速數(shù)據(jù)訪問,可以調(diào)節(jié)內(nèi)存緩存的大小,獲得最佳的性能。
[0004]Trinity是由微軟亞洲研宄院設(shè)計的基于內(nèi)存云的圖計算引擎。采用基于內(nèi)存的Key-Value存儲,其中key是圖頂點的唯一 ID,用以定位尋址cell,cell是包含該頂點鄰域內(nèi)的相鄰頂點信息的任意長度的連續(xù)內(nèi)存字節(jié)塊。圖數(shù)據(jù)的每個頂點對應(yīng)一個cell,cell存儲在trunk中,trunk是大小不超過2GB的連續(xù)內(nèi)存。
[0005]Redis也采用Key-Value存儲,但是Redis只能處理集群內(nèi)存可以容納下的圖數(shù)據(jù)。
[0006]Neo4j是采用Key-Value存儲模型的圖數(shù)據(jù)庫,然而當(dāng)圖數(shù)據(jù)規(guī)模顯著大于內(nèi)存緩存的大小時,其性能也隨著顯著降低;當(dāng)訪問異地數(shù)據(jù)時,Neo4j采用按需請求的方式,無法充分利用帶寬。
[0007]Trinity是由微軟亞洲研宄院設(shè)計的基于內(nèi)存云的圖計算引擎。當(dāng)數(shù)據(jù)頻繁更新時,插入和刪除等操作會使得cell變大或者縮小。當(dāng)cell變大之后,現(xiàn)有的存儲區(qū)域無法容納,就需要開辟更大的存儲空間裝載cell,將cell從原來位置移動到新的位置;當(dāng)cell縮小之后,原來的存儲cell的空間中縮小的部分空余出,會產(chǎn)生很多內(nèi)存碎片。由此可見,cell的增大和縮小會形成大量的內(nèi)存碎片,從而削弱內(nèi)存的利用率。Trinity采用內(nèi)存緊縮和預(yù)分配更大內(nèi)存的方式解決外部碎片的問題。不過無論采用何種方法,數(shù)據(jù)在內(nèi)存中的搬運移動是不可避免的,并且該操作是非常耗時的。因此,在圖數(shù)據(jù)頻繁更新的場景下,Trinity的性能表現(xiàn)不理想。在Trinity中,當(dāng)內(nèi)存無法容納全部圖數(shù)據(jù)時,部分trunk會位于磁盤上。當(dāng)請求的cell不在內(nèi)存時,就需要將目標(biāo)trunk全部換入內(nèi)存,由于圖數(shù)據(jù)訪問具有隨機性,數(shù)據(jù)訪問的局部性很差,多個連續(xù)請求的cell有可能不在換入內(nèi)存的trunk中,因此需要將新的trunk換入。在遠(yuǎn)程數(shù)據(jù)訪問方面,Trinity采用按需請求的方式。
[0008]Redis也采用Key-Value存儲,當(dāng)圖數(shù)據(jù)的數(shù)據(jù)量不斷增長,超過內(nèi)存容量時,只能依賴增加機器節(jié)點數(shù)目方式。當(dāng)集群規(guī)模增加時,需要重新劃分?jǐn)?shù)據(jù),并且做數(shù)據(jù)迀移。Redis的數(shù)據(jù)劃分交由客戶端完成,服務(wù)端程序無法代理異地圖數(shù)據(jù)的請求。
[0009]由以上研宄工作可知,圖計算的數(shù)據(jù)訪問需求以及圖數(shù)據(jù)的自身特點對圖數(shù)據(jù)的存儲提出了挑戰(zhàn),傳統(tǒng)的數(shù)據(jù)存儲方式比如文件系統(tǒng)或者分布式文件系統(tǒng)和Key-Value存儲模型的圖數(shù)據(jù)庫難以高效的支持圖數(shù)據(jù)訪問和更新,進而不能有效的支持圖計算。因此,需要根據(jù)圖數(shù)據(jù)的訪問特性以及圖數(shù)據(jù)本身的特點設(shè)計高效的圖數(shù)據(jù)存儲系統(tǒng)。
【發(fā)明內(nèi)容】
[0010]本發(fā)明的目的在于針對社交網(wǎng)絡(luò)數(shù)據(jù)的海量性、頻繁更新、隨機訪問以及稀疏性等特點,提供一種面向大規(guī)模社交網(wǎng)絡(luò)的圖數(shù)據(jù)存儲及查詢方法。
[0011]本發(fā)明能夠滿足鄰域的隨機訪問。本發(fā)明設(shè)計了一種基于鄰域的三級圖數(shù)據(jù)存儲結(jié)構(gòu)。以頂點鄰域為基本存儲單位,頂點鄰域是由固定大小內(nèi)存block構(gòu)成的雙向鏈表,該雙向鏈表中包含該頂點的所有關(guān)聯(lián)邊的信息,block可被直接尋址。
[0012]本發(fā)明采用零移動的數(shù)據(jù)更新機制。我們設(shè)計了一種適合圖數(shù)據(jù)頻繁更新的內(nèi)存組織方法。圖數(shù)據(jù)更新時,由block池負(fù)責(zé)block的分配和回收。和回收引起頂點鄰域的縮小或者擴增時,我們只是修改雙鏈表的首尾,并且不必緊縮存儲空間消除外部碎片,也不必分配更大存儲空間,將數(shù)據(jù)從原來地方搬移到新分配的空間中。此機制不但提高了內(nèi)存的使用率,而且也解決了其他解決方案所面臨的緊縮和移動操作。
[0013]本發(fā)明采用感知應(yīng)用的遠(yuǎn)程預(yù)取策略。圖數(shù)據(jù)的單次數(shù)據(jù)請求的數(shù)據(jù)訪問量少,引起頻繁的遠(yuǎn)程1操作。使用該策略,在當(dāng)前的異地數(shù)據(jù)請求處理時,預(yù)測后續(xù)計算的所需數(shù)據(jù),然后該預(yù)測數(shù)據(jù)與當(dāng)前請求數(shù)據(jù)一同返回給客戶進程,緩存在其本地。通過該機制能夠顯著降低1次數(shù),提供數(shù)據(jù)訪問的可預(yù)測性和有效性。本發(fā)明分析總結(jié)常見的圖算法,根據(jù)每輪更新中需要參考圖中的哪些頂點,這些算法可以分為兩類,即鄰域算法和非鄰域算法。在鄰域算法中,每一輪迭代更新每個頂點屬性值時僅需訪問相鄰頂點的值。而在非鄰域算法中,更新每個頂點屬性值還需要訪問除鄰域外其它頂點的值。
[0014]本發(fā)明的技術(shù)方案為:
[0015]一種面向大規(guī)模社交網(wǎng)絡(luò)的圖數(shù)據(jù)存儲方法,其步驟為:
[0016]I)數(shù)據(jù)存儲管理器對收到的圖數(shù)據(jù)采用Key-Value方式存儲,其中以圖數(shù)據(jù)的頂點ID為Key,以頂點鄰域為Value ;
[0017]2)對每一頂點鄰域的數(shù)據(jù)存儲:將與該頂點鄰域?qū)?yīng)頂點相連的多條邊以時間戳有序存儲到固定大小的內(nèi)存塊Block中,并使用鏈表結(jié)構(gòu)將所占用的內(nèi)存塊Block構(gòu)成Block雙向鏈表,將該頂點的屬性信息和指向該Block雙向鏈表頭部和尾部的索引信息存儲到一數(shù)據(jù)結(jié)構(gòu)Vertex中。
[0018]進一步的,所述內(nèi)存塊Block由一負(fù)責(zé)存儲資源分配的Block池管理器進行分配與回收;所述Block雙向鏈表中的內(nèi)存塊Block包括三部分:第一部分為指向Block雙向鏈表中當(dāng)前內(nèi)存塊Block的前一個內(nèi)存塊Block的指針,第二部分為指向Block雙向鏈表中當(dāng)前內(nèi)存塊Block的后一個Block的指針,第三部分為當(dāng)前內(nèi)存塊Block存儲的邊。
[0019]進一步的,所述步驟2)中,當(dāng)一頂點有新邊需要存儲到頂點鄰域時,將該新邊按時間戳排序,查看Block雙向鏈表頭部的Block是否未滿,如果未滿,則將該新邊追加在該Block的頭部;如果頭部的Block已滿,則由Block池管理器分配一新的內(nèi)存塊Block并添加到該Block雙向鏈表的頭部,然后將該新邊存儲到該新內(nèi)存塊Block中。
[0020]進一步的,每一所述內(nèi)存塊Block中設(shè)有一數(shù)據(jù)域,用于保存所存邊的時間戳區(qū)間;當(dāng)對頂點領(lǐng)域中的邊進行刪除時,從Block雙向鏈表尾部的內(nèi)存塊Block開始選取一邊,如果該邊的時間戳小于尾部內(nèi)存塊Block的時間戳區(qū)間下界,則結(jié)束刪除操作,如果該邊的時間戳大于該時間戳區(qū)間的上界,則從該Block雙向鏈表末尾移除該內(nèi)存塊Block;如