Neo4j因果集羣路由策略詳解及驅動訪問

Neo4j的使用和大多數數據庫一樣,如果您只想查詢,這很簡單。使用驅動程序,創建連接,提交查詢並返回結果,如此簡單!
如果您正在使用數據庫集羣,那麼要做的事情不止這些。首先,數據庫實例不是單個節點,而是由多臺服務器組成。本文將探討Neo4j集羣如何工作以及Neo4j驅動程序如何執行查詢。

在這裏插入圖片描述

如何在Neo4j上運行查詢
在討論驅動程序之前,我們需要簡單說明Neo4j集羣如何工作以及集羣角色是什麼,這將有助於幫您瞭解驅動訪問。

1、Neo4j因果集羣

一個集羣由3個或更多Neo4j實例組成,它們使用共識協議(RAFT)彼此通信,以提供容錯和高可用性。在Neo4j集羣中,每個實例都有完整數據庫副本(該圖未分片)。集羣中的每個節點都有一個“role”:LEADER或者FOLLOWER。
在這裏插入圖片描述

1.1 集羣角色

LEADER 負責協調集羣並接受所有寫入,FOLLOWER 擴展集羣的讀負載能力,並提供高可用性的數據。如果集羣中一個節點發生故障,並且仍然擁有多數席位,則其可以繼續處理讀和寫操作。如果失去了多數席位,那麼集羣只能讀,並且不再具有 LEADER。
另外,集羣可以增加任意數量的只讀副本(READ REPLICA),它們是集羣核心節點的只讀副本,用於擴展查詢負載。它們不是正式的集羣成員,而是“tag alone”副本,可從集羣同步事務。

1.2 拓撲變化

在集羣的生命週期中,集羣角色是臨時的,而不是您配置的角色。假設您有機器 A(LEADER)、B和C。如果 A 發生故障,將在其餘節點(B和C)間選舉一個新的領導者。當 A 重新啓動時,稍後,它將重新加入集羣,但可能是 FOLLOWER。因此,角色可以在集羣的整個生命週期中進行更改。集羣正常運行,出於各種其他原因,集羣可以選舉新的LEADER ,因此,就角色本身而言,不必擔心引起任何變化。
Neo4j使用RAFT共識算法來控制集羣。

2、Neo4j驅動程序

驅動程序API包括以下四個關鍵部分,以下概念適用於Neo4j集羣和單實例。
在這裏插入圖片描述
Neo4j驅動程序API的核心部分

但是,在集羣中,由於我們正在與一組計算機通信,因此如何執行事務以及將事務轉到何處,是“路由驅動程序”控制執行的。

3、路由驅動程序

當您使用某種 Neo4j驅動程序(Java,Javascript,Python,.Net和Go)時,會有使用 bolt+routing 協議的選項。例如,您可以連接到bolt+routing://neo4j.myhost.com。
注意:
對於集羣,設置一個包含多個 A 項的 DNS 記錄,每個 A 項都指向集羣成員。
這樣,所有客戶端都可以連接到相同的 DNS 地址,但是根據集羣狀態和運行狀況,可以將不同的計算機作爲入口點。或者可以直接連接到服務器成員的 IP 地址,但是這種方式在拓撲更改時更加靈活。
如果要連接到任何單個主機或地址,則驅動程序將爲您處理路由。驅動程序將首先檢查數據庫是否具有路由功能,如果是,則將進行讀取,以保存可用讀取和寫入服務的全部或部分快照。在那之後,除非驅動程序與集羣失去聯繫並且必須重新初始化路由,否則將不使用初始主機地址。

3.1 路由表

該路由表包含提供的服務器列表ROUTE,READ和WRITE功能。該路由信息被認爲是volatile,並且會定期刷新。
在這裏插入圖片描述
Neo4j集羣路由表

驅動程序會定期刷新此信息,因爲集羣拓撲可能會根據 runtime 事件(例如計算機故障)而發生變化。通常,WRITE 節點將成爲 LEADER ,而 READ 節點將成爲集羣或只讀副本中的 FOLLOWER。
重要提示:
只讀副本不參與集羣拓撲管理,因此它們不提供路由表,僅核心節點提供路由表。這可能在Neo4j的後續發行版中有所更改。
如果您想自己嘗試一下,只需Neo4j集羣任一實例執行以下語句:

CALL dbms.cluster.routing.getRoutingTable({})
YIELD ttl, servers
UNWIND servers as server
RETURN ttl, server.role, server.addresses;

在這裏插入圖片描述
Neo4j集羣的路由表

這個特定的 Cypher 查詢僅供內部使用,並且Neo4j的將來版本可能會更改,因此不要在其中編寫代碼,但可以使您瞭解驅動程序的實際功能。

3.2 廣播地址

路由表例子中的那些地址從何而來?用戶在neo4j.conf文件中配置 dbms.connector.bolt.advertised_address 。通過這種方式,Neo4j知道將哪個地址發佈到可以聯繫到它的外部。(配置參考)
重要提示:
客戶端使用廣播地址訪問集羣,該配置非常重要,neo4j.conf顯式設置。
請確保它是可以由clients解析(而不是內網地址,比如192.168.0.5)。一個常見的錯誤與Neo4j的連接沒有配置,或將其設置爲內部私有地址,外部Internet上的客戶端無法連接,因爲它們無法弄清楚如何訪問您的數據庫!

4、連接管理

一旦建立了路由表,驅動程序就可以管理與集羣中所有不同計算機的連接池。用戶看到的通常只是會話的創建,以及從這些會話中運行查詢。驅動程序內部的實際內容看起來更像是與一組計算機(A,B等)的連接池。會話只是根據需要連接並執行查詢。
在這裏插入圖片描述
Neo4j驅動程序連接管理

這些連接是分開處理的,因此,如果服務器 A 消失並且所有這些連接最終都要超時,則您在會話級別上不必一定知道。會話仍可以訪問其他連接,並且您的應用程序可以繼續運行。正在執行的語句將失敗,並由驅動程序自動重試。
用戶使用會話執行查詢。會話是要創建的便宜對象(與連接不同,它的建立成本很高)。會話還提供了一種因果一致性的方式將工作鏈鏈接在一起的邏輯結構,這意味着您可以執行一系列事務,後續事務始終讀取同一會話中較早事務所做的寫操作。

4.1 路由查詢

現在,假設您的驅動程序將查詢發送到數據庫,我將以JavaScript爲例,此方法適用於任何語言。
我們要做的第一件事是從驅動程序中創建會話。然後,我們使用該會話執行查詢。

const session = driver.session();
session.readTransaction(tx => tx.run('MATCH (n) RETURN count(n) as value'))
.then(results => {
console.log(results.records[0].get('value'));
})
.finally(() => session.close());

驅動如何知道將查詢發送到哪裏?在此代碼示例中,我們使用了顯式事務,這意味着我們告訴驅動程序我們正在執行readTransaction。我們獲得了一個txTransaction對象,並以此運行查詢。因爲具有路由表,並且知道您正在讀取,所以它最終可能會將此查詢發送到具有該 READ 角色的節點之一。如果執行寫事務,它將被髮送到路由表的 WRITE 節點(通常是集羣 LEADER)。
如果路由驅動程序在發送查詢的位置上有多種選擇,則使用“ least connected ”策略,這有助於避免意外路由到當前太忙而無法及時響應的服務器。
在這裏插入圖片描述
最小關聯策略

4.2 自動提交事務

如果您不使用顯式事務怎麼辦?您可以參照下面的方式:

const session = driver.session();
session.run( tx => tx.run('CALL library.myProcedure()'))
.then(results => {
console.log(results.records[0].get('value'));
})
.finally(() => session.close());

在這種情況下,驅動程序無法知道讀或者寫操作,而將事務直接發送給 LEADER 。這樣,即使您沒有告訴它是需要讀還是寫,事務也應該成功。
重要提示:
Neo4j驅動程序不會解析您的Cypher來確定您正在讀取還是正在寫入。
始終使用顯式事務來告訴驅動是讀還是寫。這有助於其有效地路由查詢,並從集羣中獲得最佳利用率。如果您從未使用過顯式事務,則可能會將所有查詢負載發送給 LEADER,對其進行轟炸,同時使集羣中的其它計算機保持空閒狀態。

5、結論

在集羣部署中,Neo4j利用 bolt+routing 協議讓客戶端動態發現集羣拓撲,並使用“least connected”策略將查詢路由到集羣中的計算機。所有這些對您都是透明的,因此在用戶級別,您將看到的是創建會話,運行查詢和使用結果。
要從此設置中獲得最大收益,需要對它的工作方式有所瞭解,並且需要牢記的最重要部分如下:
1)正確配置廣播地址
2)在驅動程序代碼中使用顯式事務調用
3)DNS配置儘可能創建單個DNS記錄,所有客戶端使用該記錄訪問集羣任何節點

有關Neo4j路由驅動程序的更多信息,請參閱Neo4j驅動程序手冊原文

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章