更新歷史
在學習過程中,本文持續更新
- 2021-12-13:更新nebula官方介紹
- 2021-12-14:更新編譯與部署方式,總結importer導入方式
- 2021-12-15:更新使用用例,常見命令等
- 2021-12-16:更新nebula集群部署方式,更新Match語法使用總結
- 2021-12-17:添加raft協議示例
- 2021-12-22:添加運行環境配置要求
- 2022-01-10:添加nebula進階學習
什么是nebula graph
官方:Nebula Graph 是一款開源的、分布式的、易擴展的原生圖數據庫,能夠承載數千億個點和數萬億條邊的超大規模數據集,並且提供毫秒級查詢。
什么是圖數據庫?
圖數據庫是圖數據庫管理系統的簡稱,使用圖形化的模型進行查詢的數據庫,通過節點、邊和屬性等方式來表示和存儲數據,支持增刪改查等操作,提供在線事務處理能力。與圖數據庫對應的是圖計算引擎,提供基於圖的大數據分析能力。
Nebula Graph 作為一個典型的圖數據庫,可以將豐富的關系通過邊及其類型和屬性自然地呈現。
簡單來說,傳統的關系型數據庫,如果要查詢不同實體之間的關系,比如一層或者多層的關系時候,需要多次的KV查詢才能得到結果,而圖數據庫可以直接從點出發一次查詢與該點的深層次的關系的其他實體。
圖數據庫和關系型數據庫的區別具體介紹可以看:https://zhuanlan.zhihu.com/p/50171330
舉個例子
在推薦召回中的swingi2i召回模型中,使用傳統的kv查詢我們需要
- 從用戶id去查詢一次用戶行為歷史
- 再由每個用戶行為歷史去查詢對應的相似item
一共兩次數據庫查詢,並且第二次查詢為多key的mget。
但使用圖數據庫,我們可以使用一次查詢便得到結果。
# 匹配從uuid為1的user點出發經過click連接doc點再經過swing邊連接的doc點的所有路徑
match p=(v:user{uuid:"123"})-[e:click]->(v2)-[e2:swing]->(v3) return p
甚至更直觀的我們還可以看到返回的simItem里面高度重合的部分
服務架構
Nebula Graph 由三種服務構成:Graph 服務、Meta 服務和 Storage 服務,是一種存儲與計算分離的架構。
graph 服務
Graph 服務主要負責處理查詢請求,包括解析查詢語句、校驗語句、生成執行計划以及按照執行計划執行四個大步驟。
- Parser:詞法語法解析模塊。
- Validator:語義校驗模塊。
- Planner:執行計划與優化器模塊。
- Executor:執行引擎模塊。
關於四個步驟的具體事務可以看官方介紹:https://docs.nebula-graph.com.cn/2.6.1/1.introduction/3.nebula-graph-architecture/3.graph-service/
Meta服務
META 服務架構
在集群模式下,所有 nebula-metad 進程構成了基於 Raft 協議的集群,其中一個進程是 leader,其他進程都是 follower。leader 是由多數派選舉出來,只有 leader 能夠對客戶端或其他組件提供服務,其他 follower 作為候補,如果 leader 出現故障,會在所有 follower 中選舉出新的 leader。
-
提供賬號管理功能
Meta 服務中存儲了用戶的賬號和權限信息,當客戶端通過賬號發送請求給 Meta 服務,Meta 服務會檢查賬號信息,以及該賬號是否有對應的請求權限。 -
管理分片
Meta 服務負責存儲和管理分片的位置信息,並且保證分片的負載均衡。 -
管理圖空間
Nebula Graph 支持多個圖空間,不同圖空間內的數據是安全隔離的。Meta 服務存儲所有圖空間的元數據(非完整數據),並跟蹤數據的變更,例如增加或刪除圖空間。 -
管理schema信息
Nebula Graph 是強類型圖數據庫,它的 Schema 包括 Tag、Edge type、Tag 屬性和 Edge type 屬性。Meta 服務中存儲了 Schema 信息,同時還負責 Schema 的添加、修改和刪除,並記錄它們的版本。 -
管理數據生命周期 TTL
Meta 服務存儲 TTL(Time To Live)定義信息,可以用於設置數據生命周期。數據過期后,會由 Storage 服務進行處理。 -
管理作業
Meta 服務中的作業管理模塊負責作業的創建、排隊、查詢和刪除。
Storage 服務
和Meta一樣,Storage也是用Raft協議作集群。
storage的三個服務層次
- Storage interface 層
Storage 服務的最上層,定義了一系列和圖相關的 API。API 請求會在這一層被翻譯成一組針對分片的 KV 操作。正是這一層的存在,使得 Storage 服務變成了真正的圖存儲,否則 Storage 服務只是一個 KV 存儲服務。 - Consensus 層
Storage 服務的中間層,實現了 Multi Group Raft,用於storage集群。 - Store Engine 層
Storage 服務的最底層,是一個單機版本地存儲引擎,提供對本地數據的get、put、scan等操作。
Raft 協議
Raft 就是一種用於保證多副本一致性的協議。Raft 采用多個副本之間競選的方式,贏得”超過半數”副本投票的(候選)副本成為 Leader,由 Leader 代表所有副本對外提供服務;其他 Follower 作為備份。
當該 Leader 出現異常后(通信故障、運維命令等),其余 Follower 進行新一輪選舉,投票出一個新的 Leader。Leader 和 Follower 之間通過心跳的方式相互探測是否存活,並以 Raft-wal 的方式寫入硬盤,超過多個心跳仍無響應的副本會認為發生故障。
raft故障流程
假設3個機器,3個partition, 3個副本(A, B, C),L標識為leader副本
機器1 | 機器2 | 機器3 |
---|---|---|
A1(L) | A2(L) | A3(L) |
B2 | B3 | B1 |
C3 | C1 | C2 |
假設A為Leader, 當機器1故障時,系統剩下的分區為 |
機器2 | 機器3 | |
---|---|---|
A2(L) | A3(L) | |
B3 | B1 | |
C1 | C2 |
可以看到分區1的leader故障,需要重新選出分區1的leader,假設經過選舉,選出了B1作為分區1的leader。
機器2 | 機器3 | |
---|---|---|
A2(L) | A3(L) | |
B3 | B1(L) | |
C1 | C2 |
nebula的數據模型
-
圖空間 space
圖空間用於隔離不同團隊或者項目的數據。不同圖空間的數據是相互隔離的,可以指定不同的存儲副本數、權限、分片等。 -
標簽 Tag
Tag 由一組事先預定義的屬性構成,用於定義點的類型。 -
邊類型 Edge type
Edge type 由一組事先預定義的屬性構成,用於定義邊的類型。 -
屬性 Properties
屬性是指以鍵值對(Key-value pair)形式存儲的信息。 -
點 Vertex
- 點用來保存實體對象,點是用點標識符(VID)標識的。VID在同一圖空間中唯一。VID 是一個 int64,或者 fixed_string(N)。
- 點必須有至少一個 Tag,也可以有多個 Tag。但不能沒有 Tag。
nebula 常用命令可以見:https://docs.nebula-graph.com.cn/2.6.1/2.quick-start/4.nebula-graph-crud/
編譯部署
如果使用官方編譯的包部署,可以跳過編譯部分,下面講如何在自己環境編譯nebula包。
使用docker編譯
- 本地安裝好 Docker
- 將 vesoft/nebula-dev 鏡像 pull 到本地
$ docker pull vesoft/nebula-dev
- 運行 Docker 並掛載 Nebula 源碼目錄到容器的 /home/nebula 目錄
$ docker run --rm -ti -v nebula本地路徑:/home/nebula vesoft/nebula-dev bash
- 進到/home/nebula路徑下進行編譯
$ mkdir build && cd build
$ cmake -DCMAKE_INSTALL_PREFIX=/usr/local/nebula -DENABLE_TESTING=OFF -DCMAKE_BUILD_TYPE=Release ..
$ make -j{N} # E.g., make -j2
$ make install
在線編譯
不推薦,依賴較多,比較難解決
生產環境配置要求
生產環境部署方式
- 3 個元數據服務進程 metad
- 至少 3 個存儲服務進程 storaged
- 至少 3 個查詢引擎服務進程 graphd
以上進程都無需獨占機器。例如一個由 5 台機器組成的集群:A、B、C、D、E,可以如下部署: - A:metad, storaged, graphd
- B:metad, storaged, graphd
- C:metad, storaged, graphd
- D:storaged, graphd
- E:storaged, graphd
同一個集群不要跨機房部署。 metad 每個進程都會創建一份元數據的存儲副本,因此通常只需 3 個進程。storaged 進程數量不影響圖空間數據的副本數量。
服務器配置要求(標准配置)
以 AWS EC2 c5d.12xlarge 為例:
- 處理器:48 core
- 內存:96 GB
- 存儲:2 * 900 GB, NVMe SSD
- Linux 內核:3.9 或更高版本,通過命令 uname -r 查看
- glibc:2.12 或更高版本,通過命令 ldd --version 查看
資源估算
- 存儲空間(全集群):點和邊數量 * 平均屬性的字節數 * 6
- 內存(全集群):點邊數量 * 15 字節 + RocksDB 實例數量 * (write_buffer_size * max_write_buffer_number + rocksdb_block_cache), 其中 etc/nebula-storaged.conf 文件中 --data_path 項中的每個目錄對應一個 RocksDB 實例
- 圖空間 partition 數量:全集群硬盤數量 * (2 至 10 —— 硬盤越好該值越大)
- 內存和硬盤另預留 20% buffer。
- rocksdb_block_cache官方建議 1/3 內存
關於機械硬盤和千兆網絡
Nebula Graph 設計時主要針對的硬件設備是 NVMe SSD 和萬兆網。沒有對於機械磁盤和千兆網絡做過適配,以下是一些需調整的參數:
- etc/nebula-storage.conf:
- --raft_rpc_timeout_ms= 5000 至 10000
- --rocksdb_batch_size= 4096 至 16384
- --heartbeat_interval_secs = 30 至 60
- --raft_heartbeat_interval_secs = 30 至 60
- etc/nebula-meta.conf:
- --heartbeat_interval_secs 與 etc/nebula-storage.conf 該項相同
- Spark Writer:
rate: {
timeout: 5000 至 10000
}
- go-importer:
- batchSize: 10 至 50
- concurrency: 1 至 10
- channelBufferSize:100 至 500
- 創建圖空間時partition 值為全集群硬盤數量 2 倍
注意:上面是針對機械硬盤和千兆網絡的優化,如果有SSD和萬兆網就不必設置
運行部署
安裝准備
- 若使用官方rpm包,直接rpm安裝即可。
- 若使用在線編譯,進到install目錄下執行啟動
手動部署
-
更改配置文件,將etc目錄下的nebula-xxxx-conf.default改名或者copy為nebula-xxxx-conf。
-
查看端口是否有被占用:
- nebula三個服務的默認端口:9559、9669、9779;
- 對應的三個http端口:19559、19669、19779;
- 三個http2的端口:19560、19670、19780
- 啟動前要查看這9個端口有沒有被占用。如果要修改端口的話在對應的conf文件里修改。
-
運行
# 啟動所有服務
./scripts/nebula.service start all
# 命令格式
./scripts/nebula.service [-v] [-c /path/to/config] <start|stop|restart|status|kill> <metad|graphd|storaged|all>
- 查看是否啟動成功
./scripts/nebula.service status all
三個端口都正常說明啟動成功,有某一個端口不正常,應該排查端口是否被占用,可以logs目錄下的日志查看報錯。
- 停止服務
- stop停止服務
./scripts/nebula.service stop all
雖然服務停止,但是進程並不會退出,端口的占用也不會釋放。如果要在運行環境重新部署,請使用kill原服務,
- kill 完全停止服務
./scripts/nebula.service kill all
使用nebula
客戶端連接
console 和 web端
可以連接nebula的客戶端有終端nebula-console,studio的web界面。兩個工具可以在官網下載。https://docs.nebula-graph.com.cn/2.6.1/2.quick-start/3.connect-to-nebula-graph/
nebula studio需要 v10.12.0 以上的 Node.js。
使用一鍵部署的,在部署的時候已經裝好nebula studio,直接訪問對應的ip端口即可。
啟動成功后,在瀏覽器地址欄輸入 http://ip address:7001。
如果在瀏覽器窗口中能看到以下登錄界面,表示已經成功部署並啟動 Studio。
客戶端sdk
- Nebula CPP : https://github.com/vesoft-inc/nebula-cpp
- Nebula Java:https://github.com/vesoft-inc/nebula-java/tree/v2.6.1
- Nebula Python:https://github.com/vesoft-inc/nebula-python
- Nebula Go:https://github.com/vesoft-inc/nebula-go/tree/v2.6.0
常用命令
- 創建圖空間
nebula> create space SpaceName(partition_num=15, replica_factor=1, vid_type=fixed_string(30));
注意:
- partition_num:指定一個副本中的分區數。通常為全集群硬盤數量的 5 倍。
- replica_factor:指定集群中副本的數量,通常生產環境為 3,測試環境可以為 1。由於采用多數表決原理,因此需為奇數。
- 你可以通過 SHOW HOSTS 命令檢查機器和 partition 分布情況:
- 執行命令SHOW HOSTS檢查分片的分布情況
- 選擇空間 USE SPACE
- 創建 Tag 和 Edge type
CREATE {TAG | EDGE} {<tag_name> | <edge_type>}(<property_name> <data_type>
[, <property_name> <data_type> ...])
[COMMENT = '<comment>'];
示例:
nebula> CREATE TAG player(name string, age int);
nebula> CREATE TAG team(name string);
nebula> CREATE EDGE follow(degree int);
nebula> CREATE EDGE serve(start_year int, end_year int);
- 插入點
INSERT VERTEX [IF NOT EXISTS] <tag_name> (<property_name>[, <property_name>...])
[, <tag_name> (<property_name>[, <property_name>...]), ...]
{VALUES | VALUE} <vid>: (<property_value>[, <property_value>...])
[, <vid>: (<property_value>[, <property_value>...];
INSERT VERTEX TAG名稱 Value VID:(屬性列表),示例
nebula> INSERT VERTEX player(name, age) VALUES "player100":("Tim Duncan", 42);
nebula> INSERT VERTEX player VALUES "player101":("Tony Parker", 36);
nebula> INSERT VERTEX player VALUES "player102":("LaMarcus Aldridge", 33);
nebula> INSERT VERTEX team(name) VALUES "team203":("Trail Blazers"), "team204":("Spurs");
- 插入邊
INSERT EDGE [IF NOT EXISTS] <edge_type> (<property_name>[, <property_name>...])
{VALUES | VALUE} <src_vid> -> <dst_vid>[@<rank>] : (<property_value>[, <property_value>...])
[, <src_vid> -> <dst_vid>[@<rank>] : (<property_name>[, <property_name>...]), ...];
INSERT EDGE EDGE類型名 Values src點Vid -> dts點Vid : (屬性列表)
示例
nebula> INSERT EDGE follow(degree) VALUES "player101" -> "player100":(95);
nebula> INSERT EDGE follow(degree) VALUES "player101" -> "player102":(90);
nebula> INSERT EDGE follow(degree) VALUES "player102" -> "player100":(75);
nebula> INSERT EDGE serve(start_year, end_year) VALUES "player101" -> "team204":(1999, 2018),"player102" -> "team203":(2006, 2015);
- 創建索引
CREATE {TAG | EDGE} INDEX [IF NOT EXISTS] <index_name>
ON {<tag_name> | <edge_name>} ([<prop_name_list>]) [COMMENT = '<comment>'];
示例
CREATE TAG INDEX player_index on player()
需要注意的是,索引創建后再插入的數據,並不在索引之中,數據更新后需要手動重建索引
重建索引
REBUILD TAG INDEX player_index
常用的查詢與匹配命令
MATCH匹配
MATCH的語法概括如下:
MATCH <pattern> [<WHERE clause>] RETURN <output>;
MATCH用於尋找與規則匹配的點和邊,MATCH語句使用原生索引查找起始點或邊,起始點或邊可以在模式的任何位置。即一個有效的MATCH語句,必須有一個屬性、Tag 或 Edge type 已經創建索引,或者在WHERE子句中用 id() 函數指定了特定點的 VID
- 匹配整個TAG的點
用戶可以在點的右側用:<tag_name>
表示模式中的Tag
。
nebula> MATCH (v:player) RETURN v;
+---------------------------------------------------------------+
| v |
+---------------------------------------------------------------+
| ("player105" :player{age: 31, name: "Danny Green"}) |
| ("player109" :player{age: 34, name: "Tiago Splitter"}) |
| ("player111" :player{age: 38, name: "David West"}) |
+---------------------------------------------------------------+
- 匹配符合屬性的點
用戶可以在Tag
的右側用{<prop_name>: <prop_value>}
表示模式中點的屬性。
nebula> MATCH (v:player{name:"Tim Duncan"}) RETURN v;
+----------------------------------------------------+
| v |
+----------------------------------------------------+
| ("player100" :player{age: 42, name: "Tim Duncan"}) |
+----------------------------------------------------+
同樣可以使用where
語句來實現
nebula> MATCH (v:player) WHERE v.name == "Tim Duncan" RETURN v;
- 匹配指定ID的多個點
可以使用點 ID 去匹配點。id()
函數可以檢索點的 ID。如果要匹配多個點,可以用IN指定ID列表
nebula> MATCH (v:player { name: 'Tim Duncan' })--(v2) \
WHERE id(v2) IN ["player101", "player102"] \
RETURN v2;
+-----------------------------------------------------------+
| v2 |
+-----------------------------------------------------------+
| ("player101" :player{age: 36, name: "Tony Parker"}) |
| ("player102" :player{age: 33, name: "LaMarcus Aldridge"}) |
+-----------------------------------------------------------+
- 匹配有邊連接的兩個點
- 可以使用
--
符號表示兩個方向的邊,並匹配這些邊連接的點。 - 可以在
--
符號上增加<
或>
符號指定邊的方向。-->
表示出邊<--
表示入邊
# 查詢:與屬性name為Tim Duncan的點有邊連接的所有點的name
nebula> MATCH (v:player{name:"Tim Duncan"})--(v2) \
RETURN v2.name AS Name;
+---------------------+
| Name |
+---------------------+
| "Spurs" |
| "Tony Parker" |
| "LaMarcus Aldridge" |
| "Marco Belinelli" |
...
# 查詢:從屬性name為Tim Duncan的點出發的邊所指向的所有點的name
nebula> MATCH (v:player{name:"Tim Duncan"})-->(v2) \
RETURN v2.name AS Name;
+-----------------+
| Name |
+-----------------+
| "Spurs" |
| "Tony Parker" |
| "Manu Ginobili" |
+-----------------+
- 匹配更深層次的連接關系
比如QQ上面我們需要去匹配某個人的好友的好友,也就是共同好友的關系
# 查詢:與屬性name為Tim Duncan點有連接的所有點的它們的所有有連接的點
nebula> MATCH (v:player{name:"Tim Duncan"})-->(v2)<--(v3) \
RETURN v3.name AS Name;
+---------------------+
| Name |
+---------------------+
| "Dejounte Murray" |
| "LaMarcus Aldridge" |
| "Marco Belinelli" |
...
這個層次還可以繼續往下查詢得更深,比如有個觀點大概就是,這個社交網絡中任意兩人之間的關系間隔不超過五個人,於是我們便可以通過圖數據庫去查詢和自己有5層連接深度關系的所有點,看看是否能夠覆蓋整個網絡。而這個種操作在傳統的關系型數據庫使用kv查詢是很難實現的。
- 匹配路徑
點與點之間的連接構成一條路徑,查詢時可以使用自定義變量名來命名路徑
# 匹配以屬性name為Tim Duncan的點為起點的所有路徑
nebula> MATCH p=(v:player{name:"Tim Duncan"})-->(v2) \
RETURN p;
+--------------------------------------------------------------------------------------------------------------------------------------+
| p |
+--------------------------------------------------------------------------------------------------------------------------------------+
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:serve@0 {end_year: 2016, start_year: 1997}]->("team204" :team{name: "Spurs"})> |
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player101" :player{age: 36, name: "Tony Parker"})> |
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player125" :player{age: 41, name: "Manu Ginobili"})> |
+--------------------------------------------------------------------------------------------------------------------------------------+
- 匹配邊
查詢時可以在方括號中使用自定義變量命名邊。例如-[e]-
。
匹配:與屬性name為Tim Duncan的點有連接的所有邊
nebula> MATCH (v:player{name:"Tim Duncan"})-[e]-(v2) \
RETURN e;
+-----------------------------------------------------------------------+
| e |
+-----------------------------------------------------------------------+
| [:serve "player100"->"team204" @0 {end_year: 2016, start_year: 1997}] |
| [:follow "player101"->"player100" @0 {degree: 95}] |
| [:follow "player102"->"player100" @0 {degree: 75}] |
...
- 匹配EDGE TYPE
和點一樣,用戶可以用:<edge_type>表示模式中的 Edge type,例如-[e:follow]-
。
匹配edge type為follow的邊
nebula> MATCH ()-[e:follow]-() RETURN e;
+-----------------------------------------------------+
| e |
+-----------------------------------------------------+
| [:follow "player104"->"player105" @0 {degree: 60}] |
| [:follow "player113"->"player105" @0 {degree: 99}] |
| [:follow "player105"->"player100" @0 {degree: 70}] |
...
- 匹配多個EDGE TYPE
使用|
可以匹配多個 Edge type,例如[e:follow|:serve]
。第一個 Edge type 前的英文冒號:
不可省略,后續 Edge type 前的英文冒號可以省略,例如[e:follow|serve]
。
nebula> MATCH (v:player{name:"Tim Duncan"})-[e:follow|:serve]->(v2) RETURN e;
+---------------------------------------------------------------------------+
| e |
+---------------------------------------------------------------------------+
| [:follow "player100"->"player101" @0 {degree: 95}] |
| [:follow "player100"->"player125" @0 {degree: 95}] |
| [:serve "player100"->"team204" @0 {end_year: 2016, start_year: 1997}] |
+---------------------------------------------------------------------------+
- 匹配多條邊
# 匹配從點Tim Duncan出發所有邊的所有入端點v2和與之有server邊連接的出端點v3
nebula> MATCH (v:player{name:"Tim Duncan"})-[]->(v2)<-[e:serve]-(v3) \
RETURN v2, v3;
+----------------------------------+-----------------------------------------------------------+
| v2 | v3 |
+----------------------------------+-----------------------------------------------------------+
| ("team204" :team{name: "Spurs"}) | ("player104" :player{age: 32, name: "Marco Belinelli"}) |
| ("team204" :team{name: "Spurs"}) | ("player101" :player{age: 36, name: "Tony Parker"}) |
| ("team204" :team{name: "Spurs"}) | ("player102" :player{age: 33, name: "LaMarcus Aldridge"}) |
...
- 匹配定長路徑的邊
可以在模式中使用:<edge_type>*<hop>
匹配定長路徑。hop
必須是一個非負整數。
# 匹配從Tim Duncan點出發長度為2的路徑
# 注意:匹配多跳路徑的時候,e不再是一條邊,而是一個hop大小的e的list
nebula> MATCH p=(v:player{name:"Tim Duncan"})-[e:follow*2]->(v2) \
RETURN DISTINCT v2 AS Friends;
+-----------------------------------------------------------+
| Friends |
+-----------------------------------------------------------+
| ("player100" :player{age: 42, name: "Tim Duncan"}) |
| ("player125" :player{age: 41, name: "Manu Ginobili"}) |
| ("player102" :player{age: 33, name: "LaMarcus Aldridge"}) |
+-----------------------------------------------------------+
- 匹配邊長路徑
用戶可以在模式中使用:<edge_type>*[minHop]..<maxHop>
匹配變長路徑。
# 匹配從Tim Duncan點出發長度為1~3的路徑
nebula> MATCH p=(v:player{name:"Tim Duncan"})-[e:follow*1..3]->(v2) \
RETURN v2 AS Friends;
+-----------------------------------------------------------+
| Friends |
+-----------------------------------------------------------+
| ("player101" :player{age: 36, name: "Tony Parker"}) |
| ("player125" :player{age: 41, name: "Manu Ginobili"}) |
| ("player100" :player{age: 42, name: "Tim Duncan"}) |
...
更多命令見官方文檔:https://docs.nebula-graph.com.cn/2.6.1/2.quick-start/6.cheatsheet-for-ngql-command/
nebula-importer 批量導入
Importer 可以讀取本地的 CSV 文件,然后導入數據至 Nebula Graph 圖數據庫中。在我的倉庫離線編譯的包里面已自帶nebula-importer,也可以使用官方最新包。使用方法:
./nebula-importer --config configFile.yml
配置文件示例
# 連接的Nebula Graph版本,連接2.x時設置為v2。
version: v2
description: example
# 是否刪除臨時生成的日志和錯誤數據文件。
removeTempFiles: false
clientSettings:
# nGQL語句執行失敗的重試次數。
retry: 3
# Nebula Graph客戶端並發數。
concurrency: 10
# 每個Nebula Graph客戶端的緩存隊列大小。
channelBufferSize: 128
# 指定數據要導入的Nebula Graph圖空間。
space: test
# 連接信息。
connection:
user: root
password: nebula
address: 10.97.174.132:9669
postStart:
# 配置連接Nebula Graph服務器之后,在插入數據之前執行的一些操作。
commands: |
USE search_rec_hin_graph;
# 執行上述命令后到執行插入數據命令之間的間隔。
afterPeriod: 1s
preStop:
# 配置斷開Nebula Graph服務器連接之前執行的一些操作。
commands: |
# 錯誤等日志信息輸出的文件路徑。
logPath: ./err/test.log
# CSV文件相關設置。
files:
# 數據文件的存放路徑,如果使用相對路徑,則會將路徑和當前配置文件的目錄拼接。本示例第一個數據文件為點的數據。
- path: ./test.csv
# 插入失敗的數據文件存放路徑,以便后面補寫數據。
failDataPath: ./err/search_rec_hin_grapherr.csv
# 讀取數據的行數限制。
limit: 10
# 是否按順序在文件中插入數據行。如果為false,可以避免數據傾斜導致的導入速率降低。
inOrder: true
# 文件類型,當前僅支持csv。
type: csv
csv:
# 是否有表頭。
withHeader: false
# 是否有LABEL。
withLabel: false
# 指定csv文件的分隔符。只支持一個字符的字符串分隔符。
delimiter: ","
schema:
# Schema的類型,可選值為vertex和edge。
type: vertex
vertex:
# 點ID設置。
vid:
# 點ID對應CSV文件中列的序號。CSV文件中列的序號從0開始。
index: 0
# 點ID的數據類型,可選值為int和string,分別對應Nebula Graph中的INT64和FIXED_STRING。
type: string
# 標簽設置。
tags:
# 標簽名稱。
- name: query
# 標簽內的屬性設置。
props:
# 屬性名稱。
- name: query
# 屬性數據類型。
type: string
# 屬性對應CSV文件中列的序號。
index: 1
- name: lang
type: string
index: 2
- name: region
type: string
index: 3
點配置
邊配置
schema:
type: edge
edge:
name: follow
withRanking: true
srcVID:
type: string
index: 0
dstVID:
type: string
index: 1
rank:
index: 2
props:
- name: degree
type: double
index: 3
使用Exchange導入
Exchange可以將不同數據源的數據導入到nebula數據庫,便於遷移數據。
支持的數據列表:
詳情:https://docs.nebula-graph.com.cn/2.6.1/nebula-exchange/use-exchange/ex-ug-import-from-csv/
nebula集群
現在我們用2台機器舉例做部署方案(這里只是舉例,在實際的生產環境中建議5個節點以上的集群,才能發揮集群的可靠性優勢)
步驟1:將nebula的安裝解壓到兩台機器上
步驟2:修改每個服務器上的Nebula Graph配置文件。
Nebula Graph的所有配置文件均位於安裝目錄的etc目錄內,包括nebula-graphd.conf、nebula-metad.conf和nebula-storaged.conf,用戶可以只修改所需服務的配置文件。
機器A配置
nebula-graphd.conf
########## networking ##########
# Comma separated Meta Server Addresses
--meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559
# Local IP used to identify the nebula-graphd process.
# Change it to an address other than loopback if the service is distributed or
# will be accessed remotely.
--local_ip=192.168.10.111
# Network device to listen on
--listen_netdev=any
# Port to listen on
--port=9669
nebula-storaged.conf
########## networking ##########
# Comma separated Meta server addresses
--meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559
# Local IP used to identify the nebula-storaged process.
# Change it to an address other than loopback if the service is distributed or
# will be accessed remotely.
--local_ip=192.168.10.111
# Storage daemon listening port
--port=9779
nebula-metad.conf
########## networking ##########
# Comma separated Meta Server addresses
--meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559
# Local IP used to identify the nebula-metad process.
# Change it to an address other than loopback if the service is distributed or
# will be accessed remotely.
--local_ip=192.168.10.111
# Meta daemon listening port
--port=9559
機器B配置
nebula-graphd.conf
########## networking ##########
# Comma separated Meta Server Addresses
--meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559
# Local IP used to identify the nebula-graphd process.
# Change it to an address other than loopback if the service is distributed or
# will be accessed remotely.
--local_ip=192.168.10.112
# Network device to listen on
--listen_netdev=any
# Port to listen on
--port=9669
nebula-storaged.conf
########## networking ##########
# Comma separated Meta server addresses
--meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559
# Local IP used to identify the nebula-storaged process.
# Change it to an address other than loopback if the service is distributed or
# will be accessed remotely.
--local_ip=192.168.10.112
# Storage daemon listening port
--port=9779
nebula-metad.conf
########## networking ##########
# Comma separated Meta Server addresses
--meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559
# Local IP used to identify the nebula-metad process.
# Change it to an address other than loopback if the service is distributed or
# will be accessed remotely.
--local_ip=192.168.10.112
# Meta daemon listening port
--port=9559
其實從上面可以看出,相比單機部署,集群部署的配置文件的最大不同點在於三個配置文件的meta_server_addrs
需要填各個節點的ip端口
踩坑注意:配置文件里默認的local ip為127.0.0.1,需要改成機器實際的ip地址,否則部署集群的時候會有一些奇怪的錯誤
步驟3:啟動,啟動流程如下
- 先啟動兩台機器的meta服務。
- 保證meta服務正常起來后,在分別啟動兩台機器的graph和storage服務
nebula 進階學習
- nebula graphd服務代碼走讀:
https://www.cnblogs.com/gitpull/p/15988828.html