Jepsen 測試框架在圖數(shù)據(jù)庫 Nebula Graph 中的實踐

產(chǎn)品細節(jié)

在本篇文章中主要介紹圖數(shù)據(jù)庫 Nebula Graph 在 Jepsen 這塊的實踐裆悄。

Jepsen 簡介

Jepsen 是一款用于系統(tǒng)測試的開源軟件庫梧油,致力于提高分布式數(shù)據(jù)庫、隊列鳞疲、共識系統(tǒng)等的安全性奴迅。作者 Kyle Kingsbury 使用函數(shù)式編程語言 Clojure 編寫了這款測試框架,并對多個著名的分布式系統(tǒng)和數(shù)據(jù)庫進行了一致性測試岖瑰。目前 Jepsen 仍在 GitHub 保持活躍,能否通過 Jepsen 的測試已經(jīng)成為各個分布式數(shù)據(jù)庫對自身檢驗的一個標(biāo)桿砂代。

Jepsen 的測試流程

流程圖

Jepsen 測試推薦使用 Docker 搭建集群蹋订。默認情況下由 6 個 container 組成,其中一個是控制節(jié)點(control node)刻伊,另外 5 個是數(shù)據(jù)庫的節(jié)點(默認為 n1-n5)露戒。控制節(jié)點在測試程序開始后會啟用多個 worker 進程捶箱,并發(fā)地通過 SSH 登入數(shù)據(jù)庫節(jié)點進行讀寫操作智什。

測試開始后,控制節(jié)點會創(chuàng)建一組進程丁屎,進程包含了待測試分布式系統(tǒng)的客戶端荠锭。另一個 Generator 進程產(chǎn)生每個客戶端執(zhí)行的操作,并將操作應(yīng)用于待測試的分布式系統(tǒng)晨川。每個操作的開始和結(jié)束以及操作結(jié)果記錄在歷史記錄中证九。同時,一個特殊進程 Nemesis 將故障引入系統(tǒng)共虑。

測試結(jié)束后愧怜,Checker 分析歷史記錄是否正確,是否符合一致性妈拌。用戶可以使用 Jepsen 的 knossos 中提供的驗證模型拥坛,也可以自己定義符合需求的模型對測試結(jié)果進行驗證。同時,還可以在測試中注入錯誤對集群進行干擾測試猜惋。

最后根據(jù)本次測試所規(guī)定的驗證模型對結(jié)果進行分析丸氛。

如何使用 Jepsen

使用 Jepsen 過程中可能會遇到一些問題,可以參考一下使用 Tips:

  1. 在 Jepsen 框架中著摔,用戶需要在 DB 接口中對自己的數(shù)據(jù)庫定義下載缓窜,安裝,啟動與終止操作梨撞。在終止后雹洗,可以將 log 文件清除香罐,同時也可以指定 log 的存儲位置卧波,Jepsen 會將其拷貝至 Jepsen 的 log 文件夾中,以便連同 Jepsen 自身的 log 進行分析庇茫。
  2. 用戶還需要提供訪問自己數(shù)據(jù)庫的客戶端港粱,這個客戶端可以是你用 Clojure 實現(xiàn)的,比如 etcd 的verschlimmbesserung旦签,也可以是 JDBC查坪,等等。然后需要定義 Client 接口宁炫,告訴 Jepsen 如何對你的數(shù)據(jù)庫進行操作偿曙。
  3. 在 Checker 中,你可以選擇需要的測試模型羔巢,比如望忆,性能測試(checker/perf)將會生成 latency 和整個測試過程的圖表,時間軸(timeline/html)會生成一個記錄著所有操作時間軸的 html 頁面竿秆。
  4. 另外一個不可或缺的組件就是在 nemesis 中注入想要測試的錯誤了启摄。網(wǎng)絡(luò)分區(qū)(nemesis/partition-random-halves)和殺掉數(shù)據(jù)節(jié)點(kill-node)是比較常見的注入錯誤。
  5. 在 Generator 中幽钢,用戶可以告知 worker 進程需要生成哪些操作歉备,每一次操作的時間間隔,每一次錯誤注入的時間間隔等等匪燕。

用 Jepsen 測試圖數(shù)據(jù)庫 Nebula Graph

分布式圖數(shù)據(jù)庫 Nebula Graph 主要由 3 部分組成蕾羊,分別是 meta 層,graph 層和 storage 層帽驯。

[圖片上傳失敗...(image-e66ba4-1579054256513)]

我們在使用 Jepsen 對 kv 存儲接口進行的測試中肚豺,搭建了一個由 8 個 container 組成的集群:一個 Jepsen 的控制節(jié)點,一個 meta 節(jié)點界拦,一個 graph 節(jié)點吸申,和 5 個 storage 節(jié)點,集群由 Docker-compose 啟動。需要注意的是截碴,要建立一個集群的 subnet 網(wǎng)絡(luò)梳侨,使集群可以連通,另外要安裝 ssh 服務(wù)日丹,并為 control node 與 5 個 storage 節(jié)點配置免密登入走哺。

測試中使用了 Java 編寫的客戶端程序,生成 jar 包并加入到 Clojure 程序依賴哲虾,來對 DB 進行 put丙躏,get 和 cas (compare-and-set) 操作。另外 Nebula Graph 的客戶端有自動重試邏輯束凑,當(dāng)遇到錯誤導(dǎo)致操作失敗時晒旅,客戶端會啟用適當(dāng)?shù)闹卦嚈C制以盡力確保操作成功。

Nebula-Jepsen 的測試程序目前分為三種常見的測試模型和三種常見的錯誤注入汪诉。

Jepsen 測試模型

single-register

模擬一個寄存器废恋,程序并發(fā)地對數(shù)據(jù)庫進行讀寫操作,每次成功的寫入操作都會使寄存器中存儲的值發(fā)生變化扒寄,然后通過對比每次從數(shù)據(jù)庫讀出的值是否和寄存器中記錄的值一致鱼鼓,來驗證結(jié)果是否滿足線性要求。由于寄存器是單一的该编,所以在此處我們生成唯一的 key迄本,隨機的 value 進行操作。

multi-register

一個可以存不同鍵的寄存器课竣。和單一寄存器的效果一樣嘉赎,但此處我們可以使 key 也隨機生成了。

4       :invoke :write  [[:w 9 1]]
4       :ok     :write  [[:w 9 1]]
3       :invoke :read   [[:r 5 nil]]
3       :ok     :read   [[:r 5 3]]
0       :invoke :read   [[:r 7 nil]]
0       :ok     :read   [[:r 7 2]]
0       :invoke :write  [[:w 7 1]]
0       :ok     :write  [[:w 7 1]]
1       :invoke :read   [[:r 1 nil]]
1       :ok     :read   [[:r 1 4]]
0       :invoke :read   [[:r 8 nil]]
0       :ok     :read   [[:r 8 3]]
:nemesis        :info   :start  nil
:nemesis        :info   :start  [:isolated {"n5" #{"n2" "n1" "n4" "n3"}, "n2" #{"n5"}, "n1" #{"n5"}, "n4" #{"n5"}, "n3" #{"n5"}}]
1       :invoke :write  [[:w 4 2]]
1       :ok     :write  [[:w 4 2]]
2       :invoke :read   [[:r 5 nil]]
3       :invoke :write  [[:w 1 2]]
2       :ok     :read   [[:r 5 3]]
3       :ok     :write  [[:w 1 2]]
0       :invoke :read   [[:r 4 nil]]
0       :ok     :read   [[:r 4 2]]
1       :invoke :write  [[:w 6 4]]
1       :ok     :write  [[:w 6 4]]

以上片段是截取的測試中一小部分不同的讀寫操作示例稠氮,

[圖片上傳失敗...(image-96d94b-1579054256513)]

其中最左邊的數(shù)字是執(zhí)行這次操作的 worker曹阔,也就是進程號。每發(fā)起一次操作隔披,標(biāo)志都是 invoke赃份,接下來一列會指出是 write 還是 read操作,而之后一列的中括號內(nèi)奢米,則顯示了具體的操作抓韩,比如

  • :invoke :read [[:r 1 nil]]就是讀取 key 為 1 的值,因為是 invoke鬓长,操作剛剛開始谒拴,還不知道值是什么,所以后面是 nil涉波。
  • :ok :read [[:r 1 4]] 中的 ok 則表示操作成功英上,可以看到讀取到鍵 1 對應(yīng)的值是 4炭序。

在這個片段中,還可以看到一次 nemesis 被注入的時刻苍日。

  • :nemesis :info :start nil 標(biāo)志著 nemesis 的開始惭聂,后面的的內(nèi)容 (:isolated ...) 表示了節(jié)點 n5 從整個集群中被隔離,無法與其他 DB 節(jié)點進行網(wǎng)絡(luò)通信相恃。

cas-register

這是一個驗證 CAS 操作的寄存器辜纲。除了讀寫操作外,這次我們還加入了隨機生成的 CAS 操作拦耐,cas-register 將會對結(jié)果進行線性分析耕腾。

0       :invoke :read       nil
0       :ok         :read       0
1       :invoke :cas        [0 2]
1       :ok         :cas        [0 2]
4       :invoke :read       nil
4       :ok         :read       2
0       :invoke :read       nil
0       :ok         :read       2
2       :invoke :write  0
2       :ok         :write  0
3       :invoke :cas        [2 2]
:nemesis        :info       :start  nil
0       :invoke :read       nil
0       :ok         :read       0
1       :invoke :cas        [1 3]
:nemesis        :info       :start  {"n1" ""}
3       :fail       :cas        [2 2]
1       :fail       :cas        [1 3]
4       :invoke :read       nil
4       :ok         :read       0

同樣的,在這次測試中杀糯,我們采用唯一的鍵值扫俺,比如所有寫入和讀取操作都是對鍵 "f" 執(zhí)行,在顯示上省略了中括號中的鍵火脉,只顯示是什么值牵舵。

  • :invoke :read nil 表示開始一次讀取 “f” 的值的操作柒啤,因為剛開始操作倦挂,所以結(jié)果是 nil(空)。
  • :ok :read 0 表示成功讀取到了鍵 “f” 的值為 0担巩。
  • :invoke :cas [1 2] 意思是進行 CAS 操作方援,當(dāng)讀到的值為 1 時,將值改為 2涛癌。

在第二行可以看到犯戏,當(dāng)保存的 value 是 0 時,在第 4 行 cas[0 2] 會將 value 變?yōu)?2拳话。在第 14 行當(dāng)值為 0時先匪,17 行的 cas[2 2] 就失敗了。

第 16 行顯示了 n1 節(jié)點被殺掉的操作弃衍,第 17呀非、18 行會有兩個 cas 失敗(fail)

Jepsen 錯誤注入

kill-node

Jepsen 的控制節(jié)點會在整個測試過程中镜盯,多次隨機 kill 某一節(jié)點中的數(shù)據(jù)庫服務(wù)而使服務(wù)停止岸裙。此時集群中就少了一個節(jié)點。然后在一定時間后再將該節(jié)點的數(shù)據(jù)庫服務(wù)啟動速缆,使之重新加入集群降允。

partition-random-node

Jepsen 會在測試過程中,多次隨機將某一節(jié)點與其他節(jié)點網(wǎng)絡(luò)隔離艺糜,使該節(jié)點無法與其他節(jié)點通信剧董,其他節(jié)點也無法和它通信幢尚。然后在一定時間后再恢復(fù)這一網(wǎng)絡(luò)隔離,使集群恢復(fù)原狀翅楼。

partition-random-halves

在這種常見的網(wǎng)絡(luò)分區(qū)情景下侠草,Jepsen 控制節(jié)點會將 5 個 DB 節(jié)點隨機分成兩部分,一部分為兩個節(jié)點犁嗅,另一部分為三個边涕。一定時間后恢復(fù)通信。如下圖所示褂微。

partition

測試結(jié)束后

Jepsen 會根據(jù)需求對測試結(jié)果進行分析功蜓,并得出本次測試的結(jié)果,可以看到控制臺的輸出宠蚂,本次測試是通過的式撼。

2020-01-08 03:24:51,742{GMT}    INFO    [jepsen test runner] jepsen.core: {:timeline {:valid? true},
 :linear
 {:valid? true,
  :configs
  ({:model {:value 0},
    :last-op
    {:process 0,
     :type :ok,
     :f :write,
     :value 0,
     :index 597,
     :time 60143184600},
    :pending []}),
  :analyzer :linear,
  :final-paths ()},
 :valid? true}


Everything looks good! ヽ(‘ー`)ノ

自動生成的 timeline.html 文件

Jepsen 在測試執(zhí)行過程中會自動生成一個名為 timeline.html 文件,以下為本次實踐生成的 timeline.html 文件部分截圖

[圖片上傳失敗...(image-eda2e2-1579054256514)]

上面的圖片展示了測試中執(zhí)行操作的時間軸片段求厕,每個執(zhí)行塊有對應(yīng)的執(zhí)行信息著隆,Jepsen 會將整個時間軸生成一個 HTML 文件。

Jepsen 就是這樣按照順序的歷史操作記錄進行 Linearizability 一致性驗證呀癣,這也是 Jepsen 的核心美浦。我們也可以通過這個 HTML 文件來幫助我們溯源錯誤。

Jepsen 生成的性能分析圖

下面是一些 Jepsen 生成的性能分析圖表项栏,本次實踐項目名為「basic-test」各位讀者閱讀時請自行腦補為你項目名浦辨。

[圖片上傳失敗...(image-c454a8-1579054256514)]

可以看到,這一張圖表展示了 Nebula Graph 的讀寫操作延時沼沈。其中上方灰色的區(qū)域是錯誤注入的時段流酬,在本次測試我們注入了隨機 kill node。

rate

而在這一張圖展示了讀寫操作的成功率列另,我們可以看出芽腾,最下方紅色集中突出的地方為出現(xiàn)失敗的地方,這是因為 control node 在殺死節(jié)點時終止了某個 partition 的 leader 中的 nebula 服務(wù)页衙。集群此時需要重新選舉摊滔,在選舉出新的 leader 之后,讀寫操作也恢復(fù)到正常了拷姿。

通過觀察測試程序運行結(jié)果和分析圖表惭载,可以看到 Nebula Graph 完成了本次在單寄存器模型中注入 kill-node 錯誤的測試,讀寫操作延時也均處于正常范圍响巢。

小結(jié)

Jepsen 本身也存在一些不足描滔,比如測試無法長時間運行,因為大量數(shù)據(jù)在校驗階段會造成 Out of Memory踪古。

但在實際場景中含长,許多 bug 需要長時間的壓力測試券腔、故障模擬才能發(fā)現(xiàn),同時系統(tǒng)的穩(wěn)定性也需要長時間的運行才能被驗證拘泞。但與此同時纷纫,在使用 Jepsen 對 Nebula Graph 進行測試的過程中,我們也發(fā)現(xiàn)了一些之前沒有遇到過的 Bug陪腌,甚至其中一些在使用中可能永遠也不會出現(xiàn)辱魁。

目前,我們已經(jīng)在日常開發(fā)過程中使用 Jepsen 對 Nebula Graph 進行測試诗鸭。Nebula Graph 有代碼更新后染簇,每晚都將編譯好的項目發(fā)布在 Docker Hub 中,Nebula-Jepsen 將自動下拉最新的鏡像進行持續(xù)測試强岸。

最后是 Nebula 的 GitHub 地址锻弓,歡迎大家試用,有什么問題可以向我們提 issue蝌箍。GitHub 地址:https://github.com/vesoft-inc/nebula青灼,加入 Nebula Graph 交流群,請聯(lián)系 Nebula Graph 官方小助手微信號:NebulaGraphbot

參考文獻

image
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末妓盲,一起剝皮案震驚了整個濱河市杂拨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌本橙,老刑警劉巖扳躬,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脆诉,死亡現(xiàn)場離奇詭異甚亭,居然都是意外死亡,警方通過查閱死者的電腦和手機击胜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門亏狰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人偶摔,你說我怎么就攤上這事暇唾。” “怎么了辰斋?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵策州,是天一觀的道長。 經(jīng)常有香客問我宫仗,道長够挂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任藕夫,我火速辦了婚禮孽糖,結(jié)果婚禮上枯冈,老公的妹妹穿的比我還像新娘。我一直安慰自己办悟,他們只是感情好尘奏,可當(dāng)我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著病蛉,像睡著了一般炫加。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上铺然,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天琢感,我揣著相機與錄音,去河邊找鬼探熔。 笑死驹针,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的诀艰。 我是一名探鬼主播柬甥,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼其垄!你這毒婦竟也來了苛蒲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤绿满,失蹤者是張志新(化名)和其女友劉穎臂外,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體喇颁,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡漏健,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了橘霎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蔫浆。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖姐叁,靈堂內(nèi)的尸體忽然破棺而出瓦盛,到底是詐尸還是另有隱情,我是刑警寧澤外潜,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布原环,位于F島的核電站,受9級特大地震影響处窥,放射性物質(zhì)發(fā)生泄漏嘱吗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一碧库、第九天 我趴在偏房一處隱蔽的房頂上張望柜与。 院中可真熱鬧巧勤,春花似錦、人聲如沸弄匕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽迁匠。三九已至剩瓶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間城丧,已是汗流浹背延曙。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留亡哄,地道東北人枝缔。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像蚊惯,于是被迫代替她去往敵國和親愿卸。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Nebula Graph:一個開源的分布式圖數(shù)據(jù)庫截型。作為唯一能夠存儲萬億個帶屬性的節(jié)點和邊的在線圖數(shù)據(jù)庫趴荸,Nebu...
    NebulaGraph閱讀 923評論 0 0
  • 概述 AliSQL X-Cluster(簡稱X-Cluster)是阿里巴巴數(shù)據(jù)庫團隊推出的兼容MySQL-5.7,...
    生活的探路者閱讀 940評論 0 0
  • 剛才看到一個文章,說女孩子的第一次很重要波闹。 我承認酝豪,女孩子第一次很重要。它不僅是你純潔的代表舔痪,而且對于每個女孩來...
    棄_ec17閱讀 657評論 1 6
  • 房子會哭泣寓调?是的,南方人的房子有時候也會像我們?nèi)祟愐粯映耄瑴I水漣漣。 北方人一定不能理解晌涕,就像南方人無法理解北方的暴...
    行走在琴鍵上的貓閱讀 6,888評論 151 247
  • 好想撥通你的電話滋捶, 只想聽聽你的聲音,總是不時的發(fā)個信息“干嘛呢”余黎,只想知道你是不是在忙著重窟,會不會想我…… 有一個...
    yzwjjx閱讀 267評論 0 0