【個推獨家】讓你一次性掌握Neo4j性能優化祕籍的三大狠招

image
做者| 西湖數據智能研究院高級研發工程師 無極 node

大千世界紛繁複雜,萬物之間總會有千絲萬縷的關係。隨着現代商業社會的發展,事物的關聯關係愈加錯綜複雜,傳統的關係存儲已經不能知足咱們的業務需求。「圖」做爲關係探索將來發展的風向標,能夠更爲直觀地幫助人們認知事物,挖掘數據之間的奧祕,爲數據價值的體現開闢了新天地。程序員

做爲專業的數據智能上市公司,個推在圖應用分析方面也進行了豐富的實踐。本文將講述圖的常見業務場景、Neo4j在個推的落地應用案例和優化舉措,並在此基礎上創新性地提出了個推獨有的Neo4j社區版 HA(High Availability) 方案。數據庫

01 圖

著名的柯尼斯堡七橋問題拉開了圖的新篇章。1736年, 萊昂哈德·歐拉針對該問題,進行了數學抽象,用二維矩陣予以表示,奠基了圖論的基礎。網絡

在這裏插入圖片描述

圖片來源於neo4j.com數據結構

什麼是圖?運維

圖的定義指出,圖G由兩個集合構成,記做G=<V,E> 。其中V是頂點的非空有限集合,E是邊的有限集合,邊是頂點的無序對或有序對集合。爲了更好地理解圖,咱們能夠看看下面的例子。佈局

在這裏插入圖片描述

圖片來源於neo4j.compost

圖中展現了3200個機場與60000條航線。對應圖的定義,每一個機場就是 V集合,航線則是E集合。性能

圖有哪些存儲方式?大數據

• 圖的鄰接矩陣

• 圖的鄰接表

• 有向圖的十字鏈表存儲表示

• 無向圖的鄰接多重表存儲表示

圖有哪些遍歷方式?

• 深度優先遍歷(DFS)

• 廣度優先遍歷(BFS)

圖數據庫

圖數據庫(GraphDatabase) 並不是指存儲圖片的數據庫,而是指支持以圖數據結構存儲和查詢數據的數據庫。圖數據庫是一種在線數據庫管理系統,具備處理圖數據模型的建立、讀取、更新和刪除(CRUD)操做。

在這裏插入圖片描述

圖片來源於amazon.com

圖存儲

一些圖數據庫使用原生圖存儲,這類存儲是通過優化的,而且是專門爲了存儲和管理圖而設計的。並非全部圖數據庫都使用原生圖存儲,也有一些圖數據庫將圖數據序列化,而後保存到關係型數據庫、面向對象數據庫,或其餘通用數據存儲中。

圖處理引擎

原生圖處理(也稱爲無索引鄰接)因爲其鏈接的節點在數據庫中能夠物理地指向彼此,所以被認爲是處理圖數據的最有效的方法。非原生圖處理使用其餘方法來處理CRUD操做。

圖常見業務場景
在這裏插入圖片描述

圖片來源於amazon.com

上圖中展現了圖在 社交網絡、推薦系統、知識圖譜、欺詐檢測、生命科學、網絡運維等業務場景中的應用。推薦系統是圖的一個典型應用,好比當咱們想要查詢好看的影片之時,售票軟件會根據咱們常常看的類型和風格幫咱們推薦相似的電影。

圖數據庫排名

在這裏插入圖片描述

根據 DB-Engines 統計, 2020 年圖數據庫受歡迎程度排行榜清晰地代表Neo4j 已經搶佔了圖數據庫的半壁江山。

02 Neo4j 圖數據庫

Neo4j是一個高性能的NOSQL圖形數據庫,它將結構化數據存儲在網絡上而不是表中。它是一個嵌入式的、基於磁盤的、具有徹底的事務特性的Java持久化引擎,也能夠被看做是一個高性能的圖引擎,該引擎具備成熟數據庫的全部特性。

Neo4j讓程序員工做在一個面向對象的、靈活的網絡結構下而不是嚴格、靜態的表中——但他們能夠還能享受到具有徹底的事務特性、企業級的數據庫的全部好處。

在這裏插入圖片描述

圖片來源於neo4j.com

圖中展現了Neo4j圖數據庫從存儲到分析的平臺生態。

Neo4j 社區版(4.0.6)存儲分析

在這裏插入圖片描述

圖片來源於neo4j.com

Node 存儲(15 bytes)

節點存儲文件爲 neostore.nodestore.db ,定長記錄文件,每一個記錄表明一個節點。

• inUse(1 byte)

– [x x x x,_ _ ] 1-4 表示 nextPropId的高4位

– [ _ , x x x ] 5-7 表示nextRelId的高3位

– [ _ , _ _ x ] 8 表示節點是否可用

• nextRelId (4 bytes ) : 節點關聯的第一條邊的id的低位,加上inUse中的3個bit,relId一共35個bit

• nextPropId (4 bytes):節點關聯的第一個屬性的id的低位,加上inUse中的4個bit,propId一共36個bit

• labels (5 bytes ) : 存儲label信息,前4個byte爲低位,最後一個1個byte爲高位

– [1 x x x ,_ _ ] : 第一個 bit (1)表示 內聯,2-4 表示 label 數量, 剩下的36個bit使用除法均分給每一個label,表明label的id

– [0 _ ,_ _ ] : 第一個 bit (0)表示 非內聯,則低位的36個bit表示第一個動態label記錄的id

• extra (1 byte) : [ _ , _ _ x ] 只用到最後一個bit,用來標記是否爲超級節點

邊的id長度爲35bit,即邊上限320億左右,屬性的id長度爲36bit,則屬性上限約640億。

Relationship 存儲 (34 bytes)

邊存儲文件爲 neostore.relationshipstore.db,定長記錄文件,每一個記錄表明一條邊

• inUse(1 byte)

– [x x x x,_ _ ] 1-4 表示 nextPropId的高4位

– [ _ , x x x ] 5-7 表示firstNodeId的高3位

– [ _ , _ _ x ] 8 表示節點是否可用

• firstNode(4 bytes):邊關聯的第一個節點id的低位,加上inUse中的3個bit,nodeId一共35個bit

• secondNode(4 bytes):邊關聯的第二個節點id的低位,加上relationshipType mid中的3個bit,nodeId一共35個bit

• relationshipType (4 bytes) :

– mid(2 bytes):

• [ x x x , _ , _ , _ ]:2-4表示secondNodeId的高3位

• [ _ , x x x , _ , _ ]:5-7表示first prevRelId的高3位

• [ _ , _ x , x x _ , _ _ ]:8-10表示firstNextRelId的高3位

• [ _ , _ , x x , x _ ]:11-13表示secondPrevRelId的高3位

• [ _ , _ , _ , x x x ]:14-16表示secondNextRelId的高3位

– type(2 bytes):邊類型id

• firstPrevRelId(4 bytes):第一個節點相關的前一條邊id的低位,加上relationshipType mid中的3個bit,relId一共35個bit

• firstNextRelId(4 bytes):第一個節點相關的後一條邊id的低位,加上relationshipType mid中的3個bit,relId一共35個bit

• secondPrevRelId(4 bytes):第二個節點相關的前一條邊id的低位,加上relationshipType mid中的3個bit,relId一共35個bit

• secondNextRelId(4 bytes):第二個節點相關的後一條邊id的低位,加上relationshipType mid中的3個bit,relId一共35個bit

•nextPropId (4 bytes):邊關聯的第一個屬性的id的低位,加上inUse中的4個bit,propId一共36個bit

• firstInChainMarkers(1 byte):

– [ _ , _ x _ ] :第7個bit標識是否爲第一個節點的第一條邊

– [ _ , _ _ x ] :第8個bit標識是否爲第二個節點的第一條邊

經過存儲結構咱們能夠看出,邊存儲了兩端節點的id以及兩條雙向鏈表,參考如圖:

在這裏插入圖片描述

圖片來源於neo4j.com

Neo4j大數據量讀寫優化

讀優化

在這裏插入圖片描述

當咱們遇到一個任務有不少關係的時候,若是要查詢這個任務下全部數據,則須要 match(n)掃描全部的Node,而這樣查詢效率會很是低。爲了解決這個問題,咱們仍然採用空間換時間的方式,引入了輔助 label,這樣能夠高效地抽出指定任務下的全部數據,將原來 8秒 查詢的效率優化到了 100毫秒 之內。

寫優化

在這裏插入圖片描述

Neo4j傳統的數據導入方式是要先建立Node,而後再建立Relation,接着通過 cypher(SQL) 執行計劃分析。在此過程當中,建立Node和Relation 步驟耗時少,但match 操做卻十分耗時。

爲了解決建立 Relation 的過程當中須要 match 操做而致使的耗時問題,咱們先建立 Node 與 Relation (Relation 的起點和終點與建立的Node有共同屬性 ),而後經過Node 某個特定屬性合併Node,並採用空間換時間的方案來實時寫入數據,最終將原來Node、Relation 寫入效率從 40 分鐘 縮減到了 3 分鐘 。

Tips

空間換時間與 時間換空間 是解決性能均衡問題的兩種方式,選擇時間與空間合理的平衡點能極大地提升咱們軟件的服務質量。

Neo4j社區版 HA(high availability)方案探索

在這裏插入圖片描述

通過對比分析,咱們最終選擇採用 Neo4j 圖數據庫。Neo4j企業版功能雖然較全可是價格很是昂貴,爲此咱們將目標瞄向 Neo4j社區版。而Neo4j 社區版存在不支持高可用、數據沒法備份的缺點,不利於其在業務環境下的使用,所以設計一種 HA 方案,來解決單點故障是很是有必要的。如下是 Neo4j社區版高可用的一種探索方案。

**1. Neo4j 部署master 節點與 slave 節點 ,master 可讀可寫,slave 僅可讀。

  1. 經過 lsyncd 將 Neo4j 主節點的data 目錄實時同步到 slave 的 data 目錄。
  2. slave data目錄掛載到 master 節點的特定目錄下。
  3. 定時重啓 slave 節點(Neo4j 社區版須要重啓加載同步的數據文件),容許 slave 節點與主節點之間存在必定的數據延遲。
  4. 當 master 出現故障後,驅動會鏈接一個可用的slave,「只讀 slave」提供查詢,此時沒法寫入數據,並告知用戶 master 節點發生故障,須要及時處理。**

03 總結

圖數據庫具備高度關聯的特性,能快速進行復雜關係數據處理,從而能夠有效幫助企業得到更深入的洞察力和更多的競爭優點。業內愈來愈多的公司開始佈局圖數據庫領域研究,研發本身的圖數據庫系統。做爲擁有海量數據沉澱的數據智能上市公司,個推在圖數據庫實踐領域不斷創新,持續打磨自身圖挖掘與分析技術的同時,也期待與業界一同碰撞更多的圖數據庫實踐。

參考資料:

https://db-engines.com/en/ran...

https://neo4j.com/docs/

https://www.tutorialspoint.co...

https://www.6aiq.com/article/...

https://aws.amazon.com/

https://www.tony-bro.com/post...

在這裏插入圖片描述

相關文章
相關標籤/搜索