本文首發 Nebula Graph 官網:nebula-graph.com.cn/posts/clust…git
在用戶使用 Nebula Graph 的過程當中,常常會遇到各類問題,一般咱們都會建議先經過 show hosts
查看集羣狀態。能夠說,整個 Nebula Graph 的集羣狀態都是靠心跳機制來構建的。本文將從心跳提及,幫助你瞭解 Nebula Graph 集羣各個節點之間通訊的機制。github
Nebula Graph 集羣通常包含三種節點,graphd 做爲查詢節點,storaged 做爲存儲節點,metad 做爲元信息節點。本文說的心跳,主要是指 graphd 和 storaged 按期向 metad 上報信息的這個心跳,藉助心跳,整個集羣完成了如下功能。(相關參數是 heartbeat_interval_secs
)數據庫
在 Nebula Graph 中常常說起的 raft 心跳則是用於擁有同一個 partition 的多個 storaged 之間的心跳,和本文提的心跳並不相同。緩存
當咱們啓動一個 Nebula Graph 集羣時,須要在對應的配置文件中填寫 meta_server_addrs
。graphd 和 storaged 在啓動以後,就會經過這個 meta_server_addrs
地址,向對應的 metad 發送心跳。一般來講,graphd 和 storaged 在鏈接上 metad 前是沒法對外進行服務的。當 metad 收到心跳後,會保存相關信息(見下文第 2 點),此時就可以經過 show hosts 看到對應的 storaged 節點,在 2.x 版本中,也可以經過 show hosts graph
看到 graphd 節點。markdown
在 metad 收到心跳時,會將心跳中的 ip、port、節點類型、心跳時間等等信息保存,以供後續使用(見下文)。運維
除此之外 storaged 在自身 leader 數量變化的時候也會上報 leader 信息,在 show hosts
中看到的 Leader count 和 Leader distribution 就是經過心跳彙報的。分佈式
當客戶經過 console 或者各類客戶端,對集羣的元信息進行更改以後(例如 create/drop space
、create/alter/drop tag/edge
、update configs
等等),一般在幾秒以內,整個集羣就都會更新元數據。oop
每次 graphd 和 storaged 在心跳的響應中會包含一個 last_update_time
,這個時間是由 metad 返回給各個節點的,用於告知 metad 自身最後一次更新元信息的時間。當 graphd 或者 storaged 發現 metad 的元信息有更新,就會向 metad 獲取相應信息(例如 space 信息、schema 信息、配置更改等等)。post
咱們以建立一個 tag 爲例,若是在 graphd/storaged 獲取到新建立的這個 tag 信息以前,咱們沒法插入這個 tag 數據(會報相似 No schema found 這樣的錯誤)。而當經過心跳獲取到對應信息並保存至本地緩存後,就可以正常寫入數據了。spa
how hosts
、show parts
這類命令都是經過 metad 中保存的各個節點心跳信息,組合顯示出來的。balance data
、balance leader
等運維命令,須要經過獲取當前集羣內哪些 storaged 節點是在線狀態,實際也是經過 metad 判斷最近一次心跳時間是否在閾值以內。create space
,當用戶建立一個 space 時,metad 也須要獲取 storaged 的狀態,將這個 space 的各個 partition 分配到在線的 storaged 中。以用戶容易遇到的問題爲例:假如咱們啓動一個 storaged 後,關掉並修改端口號,而後再啓動 storaged。若是這個過程足夠快,那麼經過
show hosts
能看到兩個在線的 storaged。此時,若是新建一個 space,例如CREATE space test(partition_num=10, replica_factor=1)
,這個 test space 就會分佈在先後啓動的兩個 storage 上。但若是等到在 show hosts 中看到其中一個離線後,再執行CREATE space test(partition_num=10, replica_factor=1)
,即使離線的 storaged 再啓動,也只有一個 storaged 擁有這個 space(建立 test space 時 online 的那個 storaged)。
在 18-19 年的時候,當時的心跳機制沒有這麼完善。一方面,不管元信息是否更改,都會從 metad 獲取最新的元信息。而一般來講,元信息改動不會很頻繁,按期獲取元信息有必定的資源浪費。另外一方面,想要將一個 storaged 節點加入和移除都是經過相似 add/delete hosts
這樣的命令,採起的是相似白名單的機制。對於其餘沒有認證過的節點,都沒法對外服務,這樣作當然也有一些優點,帶來的最大問題就是不夠友好。
所以,在 19 年末開始,咱們對心跳作了一系列的改動,特別鳴謝社區用戶 @zhanggguoqing。通過一段時間的驗證踩坑後,基本就造成了如今的形式。
有關心跳還有一個涉及到的問題就是 cluster.id 這個文件。它實際是爲了防止 storaged 與錯誤的 metad 通訊,大體原理以下:
meta_server_addrs
這個參數,生成一個 hash 值並保存在本地 kv 中。以上就是心跳機制大體的介紹,感興趣的你能夠參考下源碼實現,GitHub 傳送門:github.com/vesoft-inc/…。