亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

本文首發(fā)于 Nebula Graph Community 公眾號(hào)

在上次的 nebula-storage on nLive 直播中,來(lái)自 Nebula 存儲(chǔ)團(tuán)隊(duì)的負(fù)責(zé)人王玉玨(四王)同大家分享了 nebula storage 這塊的設(shè)計(jì)思考,也解答了一些來(lái)自社區(qū)小伙伴的提問(wèn)。本文整理自該場(chǎng)直播,按照問(wèn)題涉及的分類進(jìn)行順序調(diào)整,并非完全按照直播的時(shí)間先后排序。

Nebula 的存儲(chǔ)架構(gòu)

一文帶你了解 「圖數(shù)據(jù)庫(kù)」Nebula 的存儲(chǔ)設(shè)計(jì)和思考

 

整個(gè) Storage 主要分三層,最下面是 Store Engine,也 就是 RocksDB,中間是 raft 一致性協(xié)議層,最上層 storage service 提供對(duì)外的 rpc 接口,比如取點(diǎn)屬性,或者邊屬性,或者是去從某個(gè)點(diǎn)去找它的鄰居之類的接口。當(dāng)我們通過(guò)語(yǔ)句CREATE SPACE IF NOT EXISTS my_space_2 (partition_num=15, replica_factor=1, vid_type=FIXED_STRING(30)); 創(chuàng)建 space 時(shí),根據(jù)填寫(xiě)的參數(shù)將 space 劃分為多個(gè)邏輯單元成為 partition,各個(gè) partition 會(huì)落到不同機(jī)器上,同一個(gè) Partition 的多個(gè)副本會(huì)組成一個(gè)邏輯單元,并通過(guò) raft 共識(shí)算法 raft 保證一致。

Nebula 的存儲(chǔ)數(shù)據(jù)格式

一文帶你了解 「圖數(shù)據(jù)庫(kù)」Nebula 的存儲(chǔ)設(shè)計(jì)和思考

 


一文帶你了解 「圖數(shù)據(jù)庫(kù)」Nebula 的存儲(chǔ)設(shè)計(jì)和思考

 

這里著重講述為何 v2.x 會(huì)有這些數(shù)據(jù)格式的改動(dòng):在 v1.x 版本中,Nebula VID 主要是 int 類型,所以大家可以看到上圖 v1.x 中不管是點(diǎn)還是邊,它的 VID 是定長(zhǎng)的、占 8 個(gè)字節(jié)。2.x 版本開(kāi)始,為了支持 string 類型 VID,VertexID 就變成不定長(zhǎng)的 n 個(gè)字節(jié)。所以大家創(chuàng)建 Space 的時(shí)候需要指定 VID 的長(zhǎng)度,這個(gè)是最主要的改動(dòng),其他的話還有一些小的改動(dòng),去掉了時(shí)間戳。整體來(lái)說(shuō),目前的存儲(chǔ)格式更貼近圖的使用場(chǎng)景——從某個(gè)點(diǎn)開(kāi)始找它的鄰居,以 v2.x 這樣 VertexID + EdgeType 存儲(chǔ)格式來(lái)保存邊的話,可以迅速地找到某個(gè)點(diǎn)出邊。

同時(shí),v2.x 也做了 key(Nebula 底層是 KV 存儲(chǔ)的)編碼格式上的改變,簡(jiǎn)單來(lái)說(shuō)就是把點(diǎn)和邊分開(kāi)。這樣的話,取某一個(gè)點(diǎn)所有 tag 時(shí)通過(guò)一次 prefix 就可以直接掃到,避免了像 v1.x 那樣掃描點(diǎn)的過(guò)程中夾雜多個(gè)邊的問(wèn)題。

底層的數(shù)據(jù)存儲(chǔ)

針對(duì)用戶提出的“Nebula 底層如何存儲(chǔ)數(shù)據(jù)”的問(wèn)題,四王了進(jìn)行了回復(fù):Nebula 的存儲(chǔ)層使用 KV 進(jìn)行存儲(chǔ)點(diǎn)邊數(shù)據(jù)。對(duì)于一個(gè)點(diǎn)而言,key 里面存儲(chǔ) VID 和它的 tag 類型。點(diǎn)的 value 中,會(huì)根據(jù) 這個(gè) tag 的 schema,將 schema 中的各個(gè)屬性進(jìn)行編碼并存在 value 中。比如,player 這個(gè) tag 可能會(huì)有一個(gè) age 這樣一個(gè)整型年齡字段,使用存儲(chǔ)的時(shí)候會(huì)把 age 字段的值,按某種編碼保存在 value 中。再來(lái)說(shuō)下邊,邊的存儲(chǔ) key 會(huì)多幾個(gè)字段,主要是邊的起點(diǎn) ID、邊類型、ranking 及終點(diǎn)類型,通過(guò)這四元組確定唯一的邊。邊的 value 和點(diǎn)的 value 類似,根據(jù)邊的 Schema 字段定義,將各個(gè)字段進(jìn)行編碼存儲(chǔ)。這里要說(shuō)一下,Nebula 中存儲(chǔ)邊是存儲(chǔ)兩份:Nebula 中的邊是有向邊,存儲(chǔ)層會(huì)存儲(chǔ)正向邊和反向邊,這樣的好處在于使用 GO FROM 進(jìn)行遍歷查找那些點(diǎn)指向點(diǎn) A 或者點(diǎn) A 指向哪些點(diǎn)可以快速通過(guò)雙向查找實(shí)現(xiàn)。

一般來(lái)說(shuō),圖存儲(chǔ)分為切邊和切點(diǎn)兩種方式,像上面說(shuō)的 Nebula 其實(shí)采用了切邊方式:一條邊存儲(chǔ)兩份 KV。

用戶提問(wèn):為什么采用切邊方式,切點(diǎn)和切邊各自有啥利弊?

切邊的話,每一份邊存兩份,數(shù)據(jù)總量會(huì)比切點(diǎn)大很多,因?yàn)閳D數(shù)據(jù)邊的數(shù)量是遠(yuǎn)大于點(diǎn)的數(shù)量,造成邊的大量冗余,相對(duì)好處是對(duì)起點(diǎn)和它的邊進(jìn)行映射時(shí)會(huì)映射到同一個(gè) partition 上,這樣進(jìn)行一些從單個(gè)點(diǎn)觸發(fā)的 query 時(shí)會(huì)很快速得到結(jié)果。切點(diǎn)的話,由于點(diǎn)可能被分在多個(gè)機(jī)器上,更新數(shù)據(jù)時(shí)得考慮數(shù)據(jù)的一致性問(wèn)題,一般在圖計(jì)算里面切點(diǎn)的使用會(huì)更廣泛。

你問(wèn)我答

下面內(nèi)容收集于之前活動(dòng)預(yù)告的 AMA 環(huán)節(jié),以及直播時(shí)彈幕中提出的問(wèn)題。

問(wèn)題目錄

  • 邊的 value 存儲(chǔ)邊屬性嗎?
  • 強(qiáng) Schema 的設(shè)計(jì)原因
  • 存一份邊的設(shè)計(jì)
  • 圖空間如何做物理隔離
  • Meta 如何存儲(chǔ) Schema
  • 存儲(chǔ)未來(lái)規(guī)劃
  • VID 遍歷點(diǎn)和邊的原理
  • 數(shù)據(jù)預(yù)校驗(yàn)
  • Nebula 監(jiān)測(cè)
  • Nebula 的事務(wù)
  • 數(shù)據(jù)膨脹問(wèn)題
  • 磁盤容量本身不均怎么處理
  • Nebula 的 RocksDB “魔改”

邊的 value 存儲(chǔ)邊屬性嗎?

和上面底層存儲(chǔ)里講的那樣,創(chuàng)建 Edge 的 schema 時(shí)候會(huì)指定邊類型上的屬性,這些屬性會(huì)作為底層 RocksDB key 的 value 存儲(chǔ)起來(lái),這個(gè) value 的占位是定長(zhǎng)的,和下面這個(gè)問(wèn)題類似:

強(qiáng) Schema 的設(shè)計(jì)原因

強(qiáng) schema 是因?yàn)榧夹g(shù)原因還是產(chǎn)品原因? 因?yàn)榭紤]到 string 類型是變長(zhǎng)的,每行長(zhǎng)度本身就不固定,感覺(jué)跟無(wú) schema 無(wú)區(qū)別。 如果非定長(zhǎng),那查詢時(shí)怎么知道該查詢到哪里呢? 是有標(biāo)志位么?

其實(shí)本質(zhì)上原因是用強(qiáng) Schema 的好處是快,先說(shuō)下常見(jiàn)的簡(jiǎn)單數(shù)據(jù)類型,比如:int 和 double,這樣的數(shù)據(jù)類型長(zhǎng)度是固定的,我們會(huì)直接在 value 相應(yīng)的位置進(jìn)行編碼。再說(shuō)下 string 類型,在 Nebula 中有兩種 string :一種是定長(zhǎng) string,長(zhǎng)度是固定,和前面的簡(jiǎn)單數(shù)據(jù)類型一樣,在 value 的固定位置進(jìn)行編碼。另外一種是變長(zhǎng)的 string,通常來(lái)說(shuō)大家都會(huì)比較傾向于變長(zhǎng) string(靈活),非定長(zhǎng) string 會(huì)以指針形式存儲(chǔ)。

舉個(gè)例子,schema 中有個(gè)屬性是變長(zhǎng) string 類型,我們不會(huì)和簡(jiǎn)單數(shù)據(jù)類型一樣直接編碼保存,而是在相應(yīng)位置保存一個(gè) offset 指針,實(shí)際指向 value 中的第 100 個(gè)字節(jié),然后在 100 這個(gè)位置才保存這個(gè)變長(zhǎng) string。所以讀取變長(zhǎng) string 的時(shí)候,我們需要在 value 中讀兩次,第一次獲取 offset,第二次才能真正把 string 讀出來(lái)。通過(guò)這樣的形式,把所有類型的屬性都轉(zhuǎn)化成"定長(zhǎng)",這樣設(shè)計(jì)的好處是,根據(jù)要讀取的屬性和它前面所有字段的占用字節(jié)大小,可以直接計(jì)算出要讀取的字段在 value 中存儲(chǔ)的位置,并把它讀出來(lái)。讀取過(guò)程中,不需要讀取無(wú)關(guān)的字段,避免了弱 schema 需要對(duì)整個(gè) value 進(jìn)行解碼的問(wèn)題。

像 Neo4j 這種圖數(shù)據(jù)庫(kù),一般是 No Schema,這樣寫(xiě)入的時(shí)候會(huì)比較靈活,但序列化和反序列化時(shí)都會(huì)消耗一些 CPU,并且讀取的時(shí)候需要重新解碼。

追問(wèn):如果有變長(zhǎng) string,會(huì)不會(huì)導(dǎo)致每行數(shù)據(jù)長(zhǎng)度不一樣

可能 value 長(zhǎng)度會(huì)不一樣,因?yàn)楸旧硎亲冮L(zhǎng)嘛。

追問(wèn):如果每行長(zhǎng)度不一樣,為什么要強(qiáng) schema? Nebula 底層存儲(chǔ)用的 RocksDB,以 block 的形式組織,每個(gè) block 可能是 4K 大小,讀取的時(shí)候也是按 block 大小進(jìn)行讀取,而每個(gè) block 中的各個(gè) value 長(zhǎng)度可能是不一樣的。強(qiáng) schema 的好處在于讀單條數(shù)據(jù)的時(shí)候會(huì)快。

存一份邊的設(shè)計(jì)

Nebula 存邊是存儲(chǔ)了兩份,可以只存儲(chǔ)一份邊嗎?存一份邊反向查詢是否存在問(wèn)題?

其實(shí)這是一個(gè)比較好的問(wèn)題,其實(shí)在 Nebula 最早期設(shè)計(jì)中是只存一份邊的屬性,這適用于部分業(yè)務(wù)場(chǎng)景。舉個(gè)例子,你不需要任何的反向遍歷,這種情況下是完全不需要存反向邊。目前來(lái)說(shuō),存反向邊最大的意義是方便于我們做反向查詢。其實(shí)在 Nebula 比較早的版本中,準(zhǔn)確說(shuō)它是只存了反向邊的 key,邊類型的屬性值是沒(méi)有存,屬性值只存在正向邊上。它可能帶來(lái)一些問(wèn)題,雙向遍歷或者反向查詢時(shí),整個(gè)代碼邏輯包括處理流程都會(huì)比較復(fù)雜。 如果只存一份邊,反向查詢的確存在問(wèn)題。

圖空間如何做物理隔離

大家在用 Nebula 時(shí),首先會(huì)建圖空間 CREATE SPACE,在建圖空間時(shí),系統(tǒng)會(huì)分配一個(gè)唯一圖空間 ID 叫 spaceId,通過(guò) DESCRIBE SPACE 可以獲取 spaceId。然后 Storage 發(fā)現(xiàn)某臺(tái)機(jī)器要保存 space 部分?jǐn)?shù)據(jù)時(shí),會(huì)先單獨(dú)建一個(gè)額外的目錄,再建單獨(dú) RocksDB 在這個(gè)上面起 Rocks 的 instance(實(shí)例)用來(lái)保存數(shù)據(jù),通過(guò)這樣方式進(jìn)行物理隔離。這樣設(shè)計(jì)的話,有個(gè)弊端:雖然 rocksdb 的 instance,或者說(shuō)整個(gè) space 目錄是互相隔離,但有可能存在同一塊盤上,目前資源隔離還做的不夠好。

Meta 如何存儲(chǔ) Schema

我們以 CREATE TAG 為例子,當(dāng)我們建 tag 時(shí),首先會(huì)往 meta 發(fā)一個(gè)請(qǐng)求,讓它把這個(gè)信息寫(xiě)進(jìn)去。寫(xiě)入形式非常簡(jiǎn)單,先獲取 tagId,再保存 tag name。底層 RocksDB 存儲(chǔ)的 key 便是 tagId 或者是 tag name,value 是它每一個(gè)字段里面的定義,比如說(shuō),第一個(gè)字段是年齡,類型是整型 int;第二個(gè)字段是名字,類型是 string。schema 把所有字段的類型和名字全部存在 value 里,以某種序列化形式寫(xiě)到 RocksDB 中。

這里說(shuō)下,meta 和 storage 兩個(gè) service 底層都是 RocksDB 采用 kv 存儲(chǔ),只不過(guò)提供了不一樣的接口,比如說(shuō),meta 提供的接口,可能就是保存某個(gè) tag,以及 tag 上有哪些屬性;或者是機(jī)器或者 space 之類的元信息,包括像用戶權(quán)限、配置信息都是存在 meta 里。storage 也是 kv 存儲(chǔ),不過(guò)存儲(chǔ)的數(shù)據(jù)是點(diǎn)邊數(shù)據(jù),提供的接口是取點(diǎn)、取邊、取某個(gè)點(diǎn)所有出邊之類的圖操作。整體上,meta 和 storage 在 kv 存儲(chǔ)層代碼是一模一樣,只不過(guò)往上暴露的對(duì)外接口是不一樣的。

最后,storage 和 meta 是分開(kāi)存儲(chǔ)的,二者不是一個(gè)進(jìn)程且存的目錄在啟動(dòng)的時(shí)指定的也不一樣。

追問(wèn):meta 機(jī)器掛了,該怎么辦?

是這樣,通常來(lái)說(shuō) Nebula 建議 meta 以三副本方式部署。這樣的話,只掛一臺(tái)機(jī)器是沒(méi)有問(wèn)題的。如果單副本部署 meta 掛了的話,是無(wú)法對(duì) schema 進(jìn)行任何操作,包括不能創(chuàng)建 space。因?yàn)?storage 和 graph 是不強(qiáng)依賴 meta 的,只有在啟動(dòng)時(shí)會(huì)從 meta 獲取信息,之后都是定期地獲取 meta 存儲(chǔ)的信息,所以如果你在整個(gè)集群跑的過(guò)程中,meta 掛了而又不做 schema 修改的話,對(duì) graph 和 storage 是不會(huì)有任何影響的。

存儲(chǔ)未來(lái)規(guī)劃

Nebula 后面在存儲(chǔ)層有什么規(guī)劃嗎?性能,可用性,穩(wěn)定性方面

性能這塊,Nebula 底層采用了 RocksDB,而它的性能主要取決于使用方式,和調(diào)參的熟練程度,坦白來(lái)說(shuō),即便是 Facebook 內(nèi)部員工來(lái)調(diào)參也是一門玄學(xué)。再者,剛才介紹了 Nebula 的底層 key 存儲(chǔ),比如說(shuō) VID 或者是 EdgeType 在底層存儲(chǔ)的相對(duì)位置某種程度上決定了部分 Query 會(huì)有性能影響。從拋開(kāi) RocksDB 本身來(lái)說(shuō),其實(shí)還有很多性能上的事情可做:一是寫(xiě)點(diǎn)或者寫(xiě)邊時(shí),有些索引需要處理,這會(huì)帶來(lái)額外性能開(kāi)銷。此外,Compaction 和實(shí)際業(yè)務(wù) workload 也會(huì)對(duì)性能有很大影響。

穩(wěn)定性上,Nebula 底層采用 raft 協(xié)議,這是保證 Nebula Graph 不丟數(shù)據(jù)一個(gè)非常關(guān)鍵的點(diǎn)。因?yàn)橹挥羞@層穩(wěn)定了,再往下面的 RocksDB 寫(xiě)入數(shù)據(jù)才不會(huì)出現(xiàn)數(shù)據(jù)不一致或者數(shù)據(jù)丟失的情況發(fā)生。此外,Nebula 本身是按照通用型數(shù)據(jù)庫(kù)來(lái)設(shè)計(jì)的,會(huì)遇到一些通用型數(shù)據(jù)庫(kù)共同面臨的問(wèn)題,比如說(shuō) DDL 改變;而本身 Nebula 是一款分布式圖數(shù)據(jù)庫(kù),也會(huì)面臨分布式系統(tǒng)所遇到的問(wèn)題,像網(wǎng)絡(luò)隔離、網(wǎng)絡(luò)中斷、各種超時(shí)或者因?yàn)槟承┰蚬?jié)點(diǎn)掛了。上面這些問(wèn)題的話,都需要有應(yīng)對(duì)機(jī)制,比如 Nebula 目前支持動(dòng)態(tài)擴(kuò)縮容,整個(gè)流程非常復(fù)雜,需要在 meta 上、以及掛掉的節(jié)點(diǎn)、剩余“活著”的節(jié)點(diǎn)進(jìn)行數(shù)據(jù)遷移工作。在這個(gè)過(guò)程中,中間任何一步失敗都要做 Failover 處理。

可用性方面,我們后續(xù)會(huì)引入主備架構(gòu)。在有些場(chǎng)景下所涉及的數(shù)據(jù)量會(huì)比較少,不太需要存三副本,單機(jī)存儲(chǔ)即可。這種全部數(shù)據(jù)就在單機(jī)上的情況,可以減去不必要的 RPC 調(diào)用,直接換成本地調(diào)用,性能可能會(huì)有很大的提升。因?yàn)椋琋ebula 部署一共起 3 個(gè)服務(wù):meta、graph 和 storage,如果是單機(jī)部署的話,graph + storage 可以放在同一臺(tái)機(jī)器上,原先 graph 需要通過(guò) RPC 調(diào)用 storage 接口去獲取數(shù)據(jù)再回到 graph 進(jìn)行運(yùn)算。假如你的查詢語(yǔ)句是多跳查詢,從 graph 發(fā)送請(qǐng)求到 storage 這樣的調(diào)用鏈路反復(fù)執(zhí)行多次,這會(huì)導(dǎo)致網(wǎng)絡(luò)開(kāi)銷、序列化和反序列化的這些損耗提高。 當(dāng) 2 個(gè)進(jìn)程(storaged 和 graphd)合在一起,便沒(méi)有了 RPC 調(diào)用,所以性能會(huì)有個(gè)大提升。此外,這種單機(jī)情況下 CPU 利用率會(huì)很高,這也是目前 Nebula 存儲(chǔ)團(tuán)隊(duì)在做的事情,會(huì)在下一個(gè)大版本同大家見(jiàn)面。

VID 遍歷點(diǎn)和邊的原理

可以依據(jù) VID 遍歷點(diǎn)和邊?

一文帶你了解 「圖數(shù)據(jù)庫(kù)」Nebula 的存儲(chǔ)設(shè)計(jì)和思考

 


一文帶你了解 「圖數(shù)據(jù)庫(kù)」Nebula 的存儲(chǔ)設(shè)計(jì)和思考

 

從上圖你可以看到存儲(chǔ)了個(gè) Type 類型,在 v1.x 版本中無(wú)論點(diǎn)和邊 Type 類型都是一樣的,所以就會(huì)發(fā)生上面說(shuō)到過(guò)的掃描點(diǎn)會(huì)夾雜多個(gè)邊的問(wèn)題。在 v2.x 開(kāi)始,將點(diǎn)和邊的 Type 進(jìn)行區(qū)分,前綴 Type 值就不一樣了,給定一個(gè) VID,無(wú)論是查所有 tag 還是所有邊,都只需要一次前綴查詢,且不會(huì)掃描額外數(shù)據(jù)。

數(shù)據(jù)預(yù)校驗(yàn)

Nebula 是強(qiáng) Schema 的,插入數(shù)據(jù)時(shí)如何去判斷這個(gè)字段是否符合定義?

是否符合定義的話,大概是這樣,創(chuàng)建 Schema 時(shí)會(huì)要求指定某個(gè)字段是 nullable 或者是有默認(rèn)值,或者既不是 nullable 也不帶默認(rèn)值。當(dāng)我們插入一條數(shù)據(jù)的時(shí)候,插入語(yǔ)句會(huì)要求你“寫(xiě)明”各個(gè)字段的值分別是什么。而這條插入 Query 發(fā)到存儲(chǔ)層后,存儲(chǔ)層會(huì)檢查是不是所有字段值都有設(shè)置,或者寫(xiě)入值的字段是否有默認(rèn)值或者是 nullable。然后程序會(huì)去查是不是所有的字段都可以填上值。如果不是的話,系統(tǒng)會(huì)報(bào)錯(cuò),告知用戶 Query 有問(wèn)題無(wú)法寫(xiě)入。如果沒(méi)有報(bào)錯(cuò),storage 就會(huì)對(duì) value 進(jìn)行編碼,然后通過(guò) raft 最后寫(xiě)到 RocksDB 里,整個(gè)流程大概是這樣的。

Nebula 監(jiān)測(cè)

Nebula 可以針對(duì) space來(lái)進(jìn)行統(tǒng)計(jì)嗎?因?yàn)槲矣浀煤孟襻槍?duì)機(jī)器。

這個(gè)是非常好的問(wèn)題,目前答案是不能。這塊我們?cè)谝?guī)劃,這個(gè)問(wèn)題的主要原因是 metrics 較少,目前我們支持的 metrics 只有 latency、qps 還有報(bào)錯(cuò)的 qps 這三類。每個(gè)指標(biāo)有對(duì)應(yīng)的平均值、最大值、最小值,sum 和 count,以及 p99 之類參數(shù)。目前是機(jī)器級(jí)別的 metrics,后續(xù)的話會(huì)做兩個(gè)優(yōu)化:一個(gè)增多 metrics;二是按 space 級(jí)別進(jìn)行統(tǒng)計(jì),對(duì)于每個(gè)空間來(lái)說(shuō),我們會(huì)提供諸如 fetch、go、lookup 之類語(yǔ)句的 qps。上面是 graph 這邊的 metrics,而 storage 這塊因?yàn)闆](méi)有強(qiáng)資源隔離能力,還是提供集群或者單個(gè)機(jī)器級(jí)別的 metrics 而不是 space 級(jí)別的。

Nebula 的事務(wù)

nebula 2.6.0 的邊事務(wù)是怎么實(shí)現(xiàn)的呢?

先說(shuō)下邊事務(wù)的背景,背景是上面提到的 Nebula 是存了兩份邊 2 個(gè) kv,這 2 個(gè) kv 可能會(huì)存在不同的節(jié)點(diǎn)上,這會(huì)導(dǎo)致如果有臺(tái)機(jī)器掛了,其中有一條邊可能是沒(méi)有成功寫(xiě)入。所謂邊事務(wù)或者叫 TOSS,它主要解決的問(wèn)題就是當(dāng)我們遇到其中有一臺(tái)機(jī)器宕機(jī)時(shí),存儲(chǔ)層能夠保證這兩個(gè)邊(出邊和入邊)的最終一致。這個(gè)一致性級(jí)別是最終一致,沒(méi)有選擇強(qiáng)一致是因?yàn)檠邪l(fā)過(guò)程中碰到一些報(bào)錯(cuò)信息以及數(shù)據(jù)處理流程上的問(wèn)題,最后選擇了最終一致性。

再來(lái)說(shuō)下 TOSS 處理的整體流程,先往第一個(gè)要寫(xiě)入數(shù)據(jù)的機(jī)器發(fā)正向邊信息,在機(jī)器上寫(xiě)個(gè)標(biāo)記,看標(biāo)記有沒(méi)有寫(xiě)成功,如果成功了進(jìn)入到下一步,如果失敗直接報(bào)錯(cuò)。第二步的話,把反向邊信息從第一臺(tái)機(jī)器發(fā)給第二臺(tái)機(jī)器,能讓存正向邊的機(jī)器向第二臺(tái)機(jī)器發(fā)送反向邊信息的原因是,Nebula 中正反向邊只有起點(diǎn)和終點(diǎn)調(diào)換了一個(gè)位置,所以存正向邊的機(jī)器是完全可以拼出反向邊。存反向邊的機(jī)器收到之后,會(huì)直接寫(xiě)入邊,并將它的寫(xiě)入結(jié)果成功與否告訴第一臺(tái)機(jī)器。第一臺(tái)機(jī)器收到這個(gè)寫(xiě)入結(jié)果之后,假設(shè)它是成功的,它就會(huì)把之前第一步寫(xiě)的標(biāo)記刪掉,同時(shí)換成正常的邊,這時(shí)整個(gè)邊的正常寫(xiě)入流程就完成了,這是一個(gè)鏈?zhǔn)降耐綑C(jī)制。

簡(jiǎn)單說(shuō)下失敗的流程,一開(kāi)始第一臺(tái)機(jī)器寫(xiě)失敗了直接就報(bào)錯(cuò);第一臺(tái)機(jī)器成功之后,第二臺(tái)機(jī)器寫(xiě)失敗了,這種情況下機(jī)器一會(huì)有背景線程,會(huì)一直不斷嘗試修復(fù)第二臺(tái)機(jī)器的邊,保證和第一臺(tái)機(jī)器一樣。當(dāng)中比較復(fù)雜的是,第一臺(tái)機(jī)器會(huì)根據(jù)第二臺(tái)機(jī)器返回的錯(cuò)誤碼進(jìn)行處理。目前來(lái)說(shuō),所有的流程都會(huì)直接把標(biāo)記刪掉,直接換成正常的正向邊,同時(shí)寫(xiě)些更額外的標(biāo)記來(lái)表示現(xiàn)在需要恢復(fù)的失敗邊,讓它們最終保持一致。

追問(wèn):點(diǎn)沒(méi)有事務(wù)嗎?

是這樣,因?yàn)辄c(diǎn)是只存了一份,所以它是不需要事務(wù)的。一般來(lái)說(shuō),問(wèn)這個(gè)問(wèn)題的人是想強(qiáng)調(diào)點(diǎn)和邊之間的事務(wù),像插入邊時(shí)看點(diǎn)是否存在,或者刪除點(diǎn)時(shí)刪除對(duì)應(yīng)邊。目前 Nebula 的懸掛點(diǎn)的設(shè)計(jì)是出于性能上的考慮。如果要解決上面的問(wèn)題的話,會(huì)引入完整的事務(wù),但這樣性能會(huì)有個(gè)數(shù)量級(jí)的遞減。順便提下,剛說(shuō)到 TOSS 是鏈?zhǔn)叫问酵叫畔ⅲ厦嬉蔡岬侥苓@樣做的原因是因?yàn)榈谝粋€(gè)節(jié)點(diǎn)能完整拼出第二個(gè)節(jié)點(diǎn)的數(shù)據(jù)。但鏈?zhǔn)降脑拰?duì)完整的事務(wù)而言,性能下降會(huì)更嚴(yán)重,所以未來(lái)事務(wù)這塊的設(shè)計(jì)不會(huì)采納這種方式。

數(shù)據(jù)膨脹問(wèn)題

首次導(dǎo)入數(shù)據(jù)是怎么存儲(chǔ)的,因?yàn)槲野l(fā)現(xiàn)首次導(dǎo)入數(shù)據(jù)磁盤占用會(huì)較多?

大家發(fā)現(xiàn)如果磁盤占用高,一般來(lái)說(shuō)是 WAL 文件比較多。因?yàn)槲覀儗?dǎo)入的數(shù)據(jù)量一般比較大,這會(huì)產(chǎn)生大量的 wal,在 Nebula 中默認(rèn)的 wal ttl 是 4 個(gè)小時(shí),在這 4 個(gè)小時(shí)中系統(tǒng)的 WAL 日志是完全不會(huì)刪除的,這就導(dǎo)致占用的磁盤空間會(huì)非常大。此外,RocksDB 中也會(huì)寫(xiě)入一份數(shù)據(jù),相比后續(xù)集群正常運(yùn)行一段時(shí)間,這時(shí)候磁盤占用會(huì)很高。對(duì)應(yīng)的解決方法也比較簡(jiǎn)單,導(dǎo)入數(shù)據(jù)時(shí)調(diào)小 wal ttl 時(shí)間,比如只存半小時(shí)或者一個(gè)小時(shí),這樣磁盤占用率就會(huì)減少。當(dāng)然磁盤空間夠大你不做任何處理使用默認(rèn) 4 小時(shí)也 ok。因?yàn)檫^(guò)了若干個(gè)小時(shí)后,有一個(gè)背景線程會(huì)不斷去檢查哪些 wal 可以刪掉了,比如說(shuō)默認(rèn)值 4 個(gè)小時(shí)之后,一旦發(fā)現(xiàn)時(shí)過(guò)期的 wal 系統(tǒng)便會(huì)刪掉。

除了初次導(dǎo)入會(huì)有個(gè)峰值之外,線上業(yè)務(wù)實(shí)時(shí)寫(xiě)入數(shù)據(jù)量并不會(huì)很大,wal 文件也相對(duì)小。這里不建議手動(dòng)刪 wal 文件,因?yàn)榭赡軙?huì)出問(wèn)題正常按照 ttl 來(lái)自動(dòng)刪除就行。

compact 都做了什么事可以提高查詢,也減小了數(shù)據(jù)存儲(chǔ)占用? 可以看下 RocksDB 介紹和文章,簡(jiǎn)單說(shuō)下 Compaction 主要是多路歸并排序。RocksDB 是 LSM-Tree 樹(shù)結(jié)構(gòu),寫(xiě)入是 append-only 只會(huì)追加地寫(xiě),這會(huì)導(dǎo)致數(shù)據(jù)存在一定的冗余。Compaction 就是用來(lái)降低這種冗余,以 sst 作為輸入,進(jìn)行歸并排序和去除冗余數(shù)據(jù),最后再輸出一些 sst。在這個(gè)輸入輸出過(guò)程中,Compaction 會(huì)檢查同一個(gè) key 是否出現(xiàn)在 LSM 中的不同層,如果同一個(gè) key 出現(xiàn)了多次會(huì)只保留最新的 key,老 key 刪掉,這樣提高了 sst 有序的程度,同時(shí) sst 數(shù)量和 LSM-Tree 的層數(shù)可能會(huì)減小,這樣查詢時(shí)候需要讀取的 sst 數(shù)量就會(huì)減少,提高查詢效率。

磁盤容量本身不均怎么處理

不同大小的磁盤是否考慮按百分比占用,因?yàn)槲沂褂脙蓧K不同大小的磁盤,一塊占滿之后導(dǎo)數(shù)就出現(xiàn)問(wèn)題了

目前是不太好做,主要原因是存儲(chǔ) partition 分布查找是按照輪循形式進(jìn)行的,另外一個(gè)原因是 Nebula 進(jìn)行 Hash 分片,各個(gè)數(shù)據(jù)盤數(shù)據(jù)存儲(chǔ)大小趨近。這會(huì)導(dǎo)致如果兩個(gè)數(shù)據(jù)盤大小不一致,一個(gè)盤先滿了后面的數(shù)據(jù)就寫(xiě)入不進(jìn)去。解決方法可以從系統(tǒng)層進(jìn)行處理,直接把兩塊盤綁成同一塊盤,以同樣一個(gè)路徑掛載。

Nebula 的 RocksDB “魔改”

Nebula 的 RocksDB 存儲(chǔ)中,是通過(guò)列 column family 來(lái)區(qū)別 vertex 屬性嗎?

目前來(lái)說(shuō),其實(shí)我們完全沒(méi)有用 column family,只用了default column family。后續(xù)可能會(huì)用,但是不會(huì)用來(lái)區(qū)分 vertex 屬性,而是把不同 partition 數(shù)據(jù)分到不同 column family,這樣的好處是直接物理隔離。

Nebula 的魔改 wal 好像是全局 multi-raft 的 wal,但是在目錄上體現(xiàn)出來(lái)的好像每個(gè)圖空間都是單獨(dú)的 wal,這個(gè)原理是啥? 首先,Nebula 的確是 multi-raft,但沒(méi)有全局 wal 的概念。Nebula 的 wal 是針對(duì) partition 級(jí)別的,每個(gè) partition 有自己的 wal,并不存在 space 的 wal。至于為啥這么設(shè)計(jì),相對(duì)來(lái)說(shuō)現(xiàn)在實(shí)現(xiàn)方式比較容易,雖然會(huì)存在性能損耗,像多個(gè) wal 的話磁盤寫(xiě)入就是個(gè)隨機(jī)寫(xiě)入。但是對(duì) raft 而言,寫(xiě)入瓶頸并不是在這而是系統(tǒng)的網(wǎng)絡(luò)開(kāi)銷,用戶的復(fù)制操作 replication 開(kāi)銷是最大的。


Nebula 社區(qū)首屆征文活動(dòng)進(jìn)行中! 獎(jiǎng)品豐厚,全場(chǎng)景覆蓋:擼碼機(jī)械鍵盤??、手機(jī)無(wú)線充、健康小助手智能手環(huán)??,更有數(shù)據(jù)庫(kù)設(shè)計(jì)、知識(shí)圖譜實(shí)踐書(shū)籍 等你來(lái)領(lǐng),還有 Nebula 精致周邊送不停~

歡迎對(duì) Nebula 有興趣、喜鉆研的小伙伴來(lái)書(shū)寫(xiě)自己和 Nebula 有趣的故事呀~

一文帶你了解 「圖數(shù)據(jù)庫(kù)」Nebula 的存儲(chǔ)設(shè)計(jì)和思考

 

交流圖數(shù)據(jù)庫(kù)技術(shù)?加入 Nebula 交流群請(qǐng)先填寫(xiě)問(wèn)卷系統(tǒng),Nebula 小助手會(huì)拉你進(jìn)群~~

分享到:
標(biāo)簽:Nebula
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定