深入理解GlusterFS之數據均衡

2018-07-22 發表於 大道運行官網

(郭忠秋@TaoCloud)


GlusterFS是一個免費的開源分佈式文件系統,具有無中心節點、堆棧式設計、全局統一命名空間、高可用、高性能和橫向擴展等特點,在業界被廣泛使用。本文主要介紹GlusterFS的數據均衡功能(即rebalance),內容涉及數據均衡的產生背景、使用場景、基本原理、程序實現剖析、操作命令實踐、存在的問題以及需要優化的地方等,希望能夠拋磚引玉,爲讀者深入學習和理解GlusterFS起到一定的參考作用。

本文假定讀者已經熟悉了GlusterFS的一些基本概念術語以及架構組成。

1. 問題引入

1.1.    問題背景

在當今大數據時代,人們每天都在產生大量的數據,其中需要持久化的數據也越來越多,而一臺計算機的存儲容量是比較有限的,儘管可以爲其增加更多的內存和磁盤,但再怎麼增加也是有上限的,因此分佈式存儲系統便應運而生。分佈式存儲系統就是利用多個獨立的計算機來解決單個計算機無法解決的存儲數據量大的問題,對於這種系統而言,擴容(增加節點)和縮容(減少節點)是不可避免會遇到的情況,GlusterFS、Ceph、HDFS和OpenStack Swift等分佈式存儲系統均如此。

以擴容爲例,這是一個十分常見的場景,隨着數據量的增多,必然要對系統進行擴容來滿足實際需求,而擴容系統後會出現集羣內數據分佈不均衡的情況,已有數據只存在原有節點上,新增節點只會存儲後續新增的數據,這樣發展下去會造成原有節點負載過高,而新增節點可能還有很多可用空間,這就產生了不均衡(如圖1),爲了解決該問題,很多分佈式存儲系統都支持數據均衡(即rebalance)功能,GlusterFS、Ceph、HDFS和Swift等也是如此,執行數據均衡後,可以使集羣中的數據進行重新分佈,並且分佈的更加均勻(如圖2)。

圖1.png

圖1 擴容後數據均衡前示意圖

圖2.png

圖2 擴容後數據均衡後示意圖

本文主要討論GlusterFS數據均衡,接下來先介紹下GlusterFS數據均衡涉及到的相關內容,尤其是DHT(Distributed Hash Table)部分,因爲數據均衡和DHT結合的非常緊密。

GlusterFS使用DHT模塊來聚合多臺機器的物理存儲空間,形成一個單一的全局命名空間,並使用卷(Volume)這一邏輯概念來表示這樣的空間。每個卷可以包含一個或多個子卷(Subvolume),子卷也可稱爲DHT子卷,同樣是一個邏輯概念,一個子卷可以是單個brick、一個副本卷(Replica)或一個EC(Erasure Coding)卷,而副本卷和EC卷自身又都是由一組brick構成。而brick則是GlusterFS中的最基本存儲單元,表示爲一個機器上的本地文件系統導出目錄。例如,GlusterFS分佈式副本卷(雙副本)的簡化組成如圖3所示。

圖3.png

圖3 GlusterFS分佈式副本卷示意圖

DHT模塊使用基於32位哈希空間的一致性哈希算法(Davies-Meyer算法)計算文件的哈希值,並將文件存儲到其中一個DHT子卷,而目錄是GlusterFS中哈希分佈(layout)的基本單位,會在所有DHT子卷中都創建,哈希範圍保存在目錄的擴展屬性中。根據DHT算法原理,每一個DHT子卷的目錄都會被分配一個哈希子空間,即32位哈希空間(十六進制表示爲0x00000000~0xffffffff)中的一段哈希範圍,例如,0x00000000~0x55555554。

爲了在集羣內均衡地分佈文件,GlusterFS在每個目錄層次上重新劃分一次哈希空間,並且子目錄層和父目錄層的哈希分佈並無關聯。而文件的實際存儲位置,只由其父目錄上的哈希範圍決定,與其他目錄層次無關。子卷的目錄哈希空間分佈示意圖如圖4所示。

圖4.png

圖4 GlusterFS卷的目錄哈希空間分佈示意圖

根據以上介紹,可以概括GlusterFS中文件訪問的一般流程如下:

1、首先,DHT根據文件名稱計算出一個哈希值(假設圖4中file1哈希值爲0x23333333);

2、其次,根據該哈希值找到其所在的目錄哈希子空間(即0x00000000~0x55555554),也就是找到了對應的DHT子卷(即subvolume1);

3、最後,訪問對應的DHT子卷(即subvolume1)。

1.2.    使用場景

理想情況下,在一個GlusterFS卷中,會儘可能地在DHT子卷之間均衡地存儲文件,這樣可以充分發揮GlusterFS的高可靠性、高可用性和高性能。但現實中總有一些特殊情況存在,比如,集羣需要擴容等,從而導致文件分佈不均勻,因此也就需要進行數據均衡。

那麼GlusterFS中數據均衡具體指的是什麼呢?簡而言之,GlusterFS數據均衡就是必要的時候,在DHT各子卷之間遷移數據的過程,其目的是使數據在集羣中的不同節點之間儘量均勻分佈,從而使得集羣處於最佳狀態。

那麼問題來了,何時纔是數據均衡的“必要的時候”呢?主要有如下兩類場景:

(一)擴容或縮容文件系統

(二)重命名文件

1.2.1.      擴容或縮容

擴容或縮容GlusterFS按照子卷爲單位來做增減,這會使得DHT子卷的數量發生變化,從而導致每個子卷的目錄哈希範圍會被重新計算和分配,即每個子卷的目錄哈希範圍會改變。而文件的哈希值並沒有變化,如果此時有一些文件的哈希值落到了其他子卷(即不同於文件當前所在子卷),那麼這些文件應該被遷移到正確的子卷。

值得注意的是,在擴容GlusterFS後,需要手動執行gluster rebalance命令來觸發數據均衡功能。前文已經介紹了,擴容後會帶來新舊節點數據不均衡的問題,進一步發展可能會導致舊節點負載過高而出現性能問題,甚至最終影響到數據可靠性和可用性,因此,擴容後進行數據均衡是非常必要的。

而在縮容GlusterFS後,並不需要手動執行命令,縮容時會自動觸發執行數據均衡過程,這是因爲如果縮容時沒有自動進行數據均衡,那麼被剔除掉的節點或子捲上的數據將不再可用,從而會導致數據的丟失,這對於用戶來說是不可接受的,因此數據均衡在縮容時是不可或缺的,程序實現採用自動觸發方式也就理所當然了。

下面分別給出擴容和縮容後,並且執行數據均衡後的子卷目錄哈希空間分佈變化示意圖,如圖5和圖6所示。

圖5.png

圖5 擴容後子卷的目錄哈希空間分佈變化

圖6.png

圖6 縮容後子卷的目錄哈希空間分佈變化

1.2.2.      重命名文件

在GlusterFS中,重命名文件會導致該文件的哈希值發生變化,假設此時DHT子卷的數量並沒有變化,即沒有擴容和縮容,那麼每個子卷的目錄哈希範圍也就沒有變化,根據DHT算法判斷該文件的新存儲位置,如果文件的新存儲位置與當前所在子卷不同(如圖7),則該文件應該被遷移到正確的子卷。

重命名文件後,系統不會自動進行均衡,而是會在目標子捲上產生一個同名的內容爲空的鏈接文件(Link file),該鏈接文件的擴展屬性上會記錄文件的實際存儲位置(也就是原來所在的子卷)。假設此時客戶端訪問重命名後的文件,根據前面介紹的文件訪問流程,則DHT會先將請求轉到哈希計算得出的子捲去查找該文件,並獲取到鏈接文件信息,DHT模塊懂得鏈接文件的意義,從鏈接文件信息中得出文件的實際位置,然後再到實際的子卷獲取文件。

可以發現,如果重命名文件後不進行數據均衡,則客戶應用程序在訪問文件時會增加額外的步驟,從而造成一定程度的訪問延遲,當系統有大量鏈接文件時,則會導致訪問性能的大幅下降,對應用程序造成影響。而執行數據均衡後則會將文件遷移到正確的位置,消除了鏈接文件帶來的訪問延遲問題,因此數據均衡對於文件重命名來說也是很有必要的。

圖7.png

圖7 重命名文件導致的文件位置變化

2. 基本原理

前面簡要介紹了DHT模塊的基本作用和文件的一般訪問流程,目的是爲了讀者能夠更好地理解GlusterFS數據均衡。本節將介紹當前數據均衡功能是如何工作的。

隨着GlusterFS項目的發展,其數據均衡功能也在不斷的完善,其最初的工作機制和現在的工作機制已經相去甚遠,下面高度概括了數據均衡當前的流程,如圖8所示:

圖8.png

圖8 數據均衡的概括流程

爲了便於理解,以上流程是站在集羣的視角,對數據均衡流程的高度總結,具體如下:

1、掃描整個GlusterFS卷,獲取到卷中所有目錄和文件;

2、對每一個目錄,修復該目錄的哈希分佈;

3、對每一個文件,判斷該文件是否需要遷移;

4、對於需要遷移的文件,將其遷移到正確的位置。

 

可以看到,概括總結後的流程非常簡單,但是實際代碼實現卻比較複雜,一方面是考慮了各種異常情況後,會有大量的細節需要處理,另一方面是數據均衡功能的代碼與DHT的代碼結合的非常緊密,從而增加了代碼的複雜度,不便於理解。後面的實現剖析部分會具體介紹代碼級別的處理流程。

本節接下來先介紹數據均衡功能稍微細化後的工作機制,然後再給出一個實例分析,用於幫助讀者理解。

2.1.    工作機制

在GlusterFS的數據均衡功能實現中,每個節點採用單進程多線程的實現方式,其中,主線程使用類似深度優先算法,從根目錄開始,遍歷GlusterFS卷在本節點上的目錄並修復其哈希分佈,同時爬取目錄下的所有文件,根據算法將相應文件放到遷移隊列裏,並通知等待的工作線程進行遷移處理。

而工作線程則負責檢查遷移隊列裏是否有文件待遷移,若隊列不空則遷移其中的文件,一次遷移一個文件;若隊列爲空則自我睡眠,等待主線程喚醒。

主線程的文件爬取工作和工作線程的數據遷移工作同時進行,並且支持多個線程並行遷移文件。當主線程完成修復目錄和爬取文件工作後,將等待其他工作線程完成數據遷移工作,當遷移隊列裏的所有文件都被遷到正確位置後,所有工作線程結束退出,主線程收到所有工作線程的退出消息後,做一些清理工作,然後結束本節點的數據均衡進程。

下面給出稍微細化後的數據均衡主線程和遷移線程的工作流程如圖9和圖10所示。

圖9.png

圖9 數據均衡主線程的工作機制

啓動數據均衡功能後,每個節點的數據均衡進程的主線程都按照上圖流程進行,並且每個節點只處理屬於本地brick上的文件,上述流程簡要說明如下:

1、首先,修復卷的根目錄哈希分佈;

2、打開並遍歷當前目錄,獲取到所有子目錄;

3、對於當前目錄中的每個子目錄,按照如下步驟遞歸處理:

3.1、如果有未被處理的子目錄,從中選擇一個目錄,並返回到步驟2處理該子目錄;否則,下一步;

3.2、所有子目錄都已經被處理過了或者沒有子目錄,修復當前目錄的哈希分佈;

3.2.1、打開並遍歷當前目錄,獲取所有文件;

3.2.2、對於當前目錄中的每個文件,按照如下步驟處理:

3.2.2.1、如果有未被處理的文件,從中選擇一個文件,進入下一步,否則,轉到步驟3.2.2.4;

3.2.2.2、如果文件應該由本節點處理,則進入下一步,否則,轉到步驟3.2.2;

3.2.2.3、如果文件滿足遷移條件,則將文件放到一個遷移隊列,並通知遷移線程執行遷移,否則,返回步驟3.2.2;

3.2.2.4、當前目錄的所有文件已被處理過了,轉入下一步;

4、如果本節點還有目錄的哈希分佈未被修復,選擇其中的一個目錄(按照之前遍歷時的順序),並轉到步驟3,否則,進入下一步;

5、等待所有遷移線程完成數據遷移工作,然後做些清理工作,最後結束數據均衡進程。

工作線程的處理流程如下:

圖10.png

圖10 數據均衡遷移線程的工作機制

數據均衡的遷移線程處理流程簡介如下:

1、獲取到數據均衡進程的遷移隊列;

2、檢查隊列是否爲空;

2.1、如果隊列不空,則從隊列頭部取出一個文件,並處理該文件的具體遷移過程,遷移完成後返回步驟2;

2.2、如果隊列爲空,則繼續判斷主線程是否已經完成對整個卷的文件爬取;

2.2.1、如果主線程未完成文件爬取,則遷移線程進入休眠狀態,等待主線程的喚醒;

2.2.2、如果主線程已完成文件爬取,則退出線程。

2.2.    實例分析

以上內容可能有些晦澀難懂,爲了便於理解,下面舉個例子,假設GlusterFS卷中的目錄文件佈局如圖11所示:

圖11.png

圖11 GlusterFS卷的目錄文件佈局示意圖

根據上述數據均衡的工作機制,其處理順序如下:

1、數據均衡進程啓動,主線程首先修復根目錄的哈希分佈;

2、打開並遍歷根目錄,獲取到文件file1、目錄dir1和dir2;

3、選擇根目錄的一個子目錄,假設選擇dir1;

4、打開並遍歷dir1,獲取到文件file2、目錄dir3和dir4;

5、選擇dir1目錄的一個子目錄,假設選擇dir4;

6、打開並遍歷dir4,獲取到文件file5;

7、因爲dir4沒有子目錄,所以不再進行遞歸遍歷,而是修復dir4的哈希分佈;

8、遍歷dir4,獲取其下所有文件,本例爲file5;

9、判斷file5是否應該由本節點處理,假設由本節點處理;

10、判斷file5是否需要遷移,假設需要遷移;

11、將file5放到遷移隊列,通知工作線程進行遷移(遷移線程負責處理具體的遷移過程);

12、dir4目錄下沒有其他文件需要處理了,即對dir4的處理完成了,按照之前的遍歷順序,繼續處理下一個哈希分佈未修復的目錄,也就是優先選擇與dir4同一層次的其他目錄;

13、選擇dir3,由於dir3也沒有子目錄,修復dir3的哈希分佈;

14、打開並遍歷dir3,獲取到文件file4,然後同file5的處理流程一樣,不再贅述;

15、處理完dir3後,則當前同一層次的目錄都處理完了(即dir3和dir4),開始處理當前目錄層次的父目錄,即dir1;

16、完成對dir1的修復目錄、遍歷文件和遷移文件,具體步驟同dir4,不再贅述;

17、接着上面的步驟3,對dir1的同一層次的其他目錄(本例爲dir2)進行處理,過程與dir1類似,即先修復dir5哈希分佈,遷移其下文件file6,再修復dir2哈希分佈,遷移文件file3,具體過程不再贅述;

18、最後處理根目錄的文件file1,不再贅述;

19、數據均衡進程等待所有遷移線程完成數據遷移,然後正常結束。

以上處理順序的簡化示意圖如下圖12所示:

圖12.png

圖12 目錄處理與文件遷移順序

總結一下,數據均衡的當前工作機制就是多個節點同時參與處理,每個節點以單進程多線程的方式,同時掃描文件和遷移文件,並且掃描文件和遷移文件分別由不同線程處理,每個節點可以並行遷移文件,相比以往的數據均衡流程,大大增加了並行度,並且更加可擴展,使得集羣數據均衡時的系統負載分佈的更加均勻,同時效率也更高了。

3. 最佳實踐

GlusterFS爲數據均衡功能提供了相應的命令行程序,通過該程序可以和glusterd服務進程之間進行通信,用於查詢數據均衡狀態信息和控制數據均衡相關操作,可以輔助相關人員更好地控制管理數據均衡過程。

3.1.    操作命令

命令格式爲:

gluster volume rebalance <VOLNAME> {{fix-layout start} | {start [force]|stop|status}}

常用命令介紹如下:

(1)只修復目錄layout命令

gluster v rebalance VOL_NAME fix-layout start

例如:

例1.png

(2)開啓數據均衡命令

gluster v rebalance VOL_NAME start

例如:

例2.png

也可以使用強制選項,這樣可以忽略一個容量限制,即不帶強制選項時會比較文件所在的原子卷和目標子卷的剩餘容量,如果原子卷大於目標子卷,則不遷移該文件。使用強制選項則會跳過這個限制,命令如下:

gluster v rebalance VOL_NAME start force

例如:

例3.png

(3)設置數據均衡遷移速度

爲了良好的遷移性能,數據均衡進程中使用了多線程,並且支持並行遷移多個文件,但是這樣佔用一定的系統資源,對存儲系統本身性能帶來一定影響,因此,GlusterFS提供了相關控制命令,用於調控實際遷移速度的快慢,目前主要有三種模式,lazynormalaggressive。顧名思義,lazy是懶惰的慢速模式(較少線程遷移),normal是正常模式(線程數量適中),aggressive是激進模式(較多線程遷移),默認採用normal模式,可以根據實際需要去做具體設置,命令格式如下:

gluster volume set <VOLNAME> rebal-throttle lazy|normal|aggressive

例如:

例4.png

(4)查看數據均衡狀態等信息

gluster v rebalance VOL_NAME status

例如:

例5.png

    可以查看到數據均衡在每個節點的當前狀態(status)、運行了多久(run time)、掃面的文件數量(scanned)、已經遷移的文件數量(rebalanced-files)、已經遷移的數據量(size)、遷移失敗的文件數量(failures)和跳過的文件數量(skipped)。

(5)停止數據均衡進程

gluster v rebalance VOL_NAME stop

例如:

例6.png

3.2.    均衡建議

當集羣需要進行數據均衡時,建議參考如下內容:

(1)儘量提前做規劃,例如,別等到集羣存儲空間快用完了才擴容,一方面會導致時間緊迫,部署準備時間匆忙,容易忙中出錯;另一方面也容易導致舊節點之間的文件遷移失敗,最好預留出一定的剩餘空間;

(2)確保集羣所有節點處於正常狀態,卷處於啓動狀態,glusterd服務進程和brick進程狀態正常,節點之間通信正常;

(3)檢查GlusterFS卷中是否有文件損壞,如果有,則先對其進行修復;

(4)在執行數據均衡時,確保集羣沒有自修復操作正在進行,否則會影響到數據正確性和遷移效率;

(5)如果允許的話,在執行數據均衡前,停止客戶端應用,可以提高均衡效率;

(6)先執行fix-layout操作,再執行數據遷移,可以在一定程度上提高遷移效率;

(7)根據實際需要選擇遷移模式,默認是normal模式,aggressive模式可能佔用的系統資源較多,進而影響到存儲性能;

(8)數據均衡過程中,通過命令行程序定時關注均衡的當前狀態,以便及時發現問題並做相應調整;

(9)當集羣規模較大時,可能偶爾會出現某個節點均衡失敗的情況,一般重新開始執行均衡即可;

    (10)如果執行數據遷移對應用程序影響較大,可以只執行fix layout,這樣可以只修復目錄的哈希分佈,並不會實際遷移文件,此時新文件可以存儲到新增節點(或brick)上,之後再找適當時機(系統比較空閒的時候)執行數據遷移操作。

4. 實現剖析

GlusterFS數據均衡功能的代碼與DHT層代碼緊密結合在一起,主要的功能邏輯代碼位於dht-rebalance.c文件中,剩餘部分代碼包含在DHT層的其他代碼邏輯中。在數據均衡代碼的實現中,採用了syncop框架,這是一套基於協程的合作式多任務同步框架,它的存在簡化了數據均衡功能的實現。

前面的工作機制部分介紹了數據均衡的基本流程,本節則主要側重代碼級別的討論,首先簡要介紹數據均衡功能中涉及的進程交互,然後討論syncop框架,最後給出數據均衡的幾個關鍵流程。限於時間原因,忽略了很多代碼處理細節,留給讀者自行分析實踐。

4.1.    進程交互過程

下面以命令行手動觸發數據均衡爲例,簡要說明其中涉及的進程交互步驟,在命令執行的節點上,簡化的進程交互過程如下圖13所示。

圖13.png 

圖13手動觸發數據均衡的進程交互過程

交互過程主要涉及到cli、glusterd和glusterfs三個進程,簡要說明如下:

1、在集羣的一個節點上,執行gluster rebalance start命令(即啓動cli進程),該命令向本節點glusterd服務進程發起rpc連接建立請求;

2、本節點glusterd進程接收到該請求,與之建立rpc連接並回復響應;

3、cli命令進程收到rpc連接建立響應,然後向本節點glusterd進程發起啓動數據均衡請求;

4、本節點glusterd進程收到請求後,做一些初始化等準備工作,並以事務方式向集羣其他相關節點(當前GlusterFS卷的所有其他節點)的glusterd進程,發起啓動數據均衡的請求;

5、與此同時,本節點glusterd進程啓動本節點的數據均衡進程;

6、數據均衡進程以gluster客戶端進程(即glusterfs)的形式啓動,該進程使用的客戶端配置文件(即.vol文件)與正常客戶端配置文件不同,去掉了其中的性能相關模塊;

7、本節點的數據均衡進程啓動完畢後,返回響應給glusterd進程;

8、本節點glusterd進程等待並接收所有其他相關節點的響應,即數據均衡進程已經啓動完畢的消息;

9、本節點glusterd進程返回啓動數據均衡的響應,通知命令行程序啓動已經完成;

10、命令行程序從本地glusterd進程接收響應,打印輸出命令執行結果,然後退出cli程序;

11、本節點glusterd進程完成了對命令行請求的處理,等待其他請求到來;

12、本節點數據均衡進程開始處理,具體處理流程參見前文中的工作原理部分,均衡進程在處理完成後退出。

4.2.    syncop框架

在GlusterFS的幾乎所有線程中,文件操作(fops)都是異步執行的,使用的基本原語是STACK_WIND和STACK_UNWIND這一類宏定義,這類宏定義像調用函數和回調函數一樣工作,有效地實現了集羣和並行環境下的文件操作。

但在數據均衡功能中,如果直接採用這類宏定義實現相關操作,則會使程序變得非常複雜而不好控制,因此,GlusterFS開發人員引入了syncop同步框架,並廣泛使用於程序中,以方便數據均衡功能的實現,例如,用於文件爬取程序和流程控制等方面。

4.2.1.      syncop術語

 (1)syncenv

Syncenv是同步環境對象,該對象擁有一個可調度的工作線程池,同步任務(synctask)在該環境中調度執行。

(2)synctask

Synctask是同步任務對象,可以理解爲一對C語言函數指針,即調用函數指針synctask_fn_t(如syncop_lookup)和回調函數指針synctask_cbk_t(如syncop_lookup_cbk)。

Synctask有兩種操作模式:

(1)調用線程等待synctask完成;

(2)調用線程調度synctask,使之繼續運行;

Synctask能夠確保一個函數調用完成後,其對應的回調函數也會被執行到。

4.2.2.      synctask生命週期

一個synctask的完整生命週期包括如下幾個階段:

(1)CREATED

當調用synctask_create或synctask_new函數創建一個synctask時;

(2)RUNNABLE

當把synctask加入到syncenv的runq隊列時;

(3)RUNNING

當syncenv的工作線程調用synctask_switch_to函數時;

(4)WAITING

當調用synctask_yield函數將一個synctask加入到syncenv的waitq隊列時;

(5)DONE

當一個synctask完成運行時。

以上幾個階段的狀態轉換如下圖14所示:

圖14.png

圖14 synctask狀態轉換

需要注意的是,在synctask的生命週期內,並不能保證該任務是一直在同一個線程中運行,每次調用synctask_yield函數時,可能會使其運行於一個不同的線程中。

總之,可以這樣簡單地理解,使用syncop框架執行一個任務時(例如syncop_opendir函數用於打開目錄),調用函數會等待該任務完成後(目錄已被打開),再繼續往下進行。相對而言,syncop框架大大簡化了數據均衡功能的實現。

 

4.3.    關鍵處理流程

每個節點的數據均衡進程,在處理流程上都是一樣的,下面結合實際代碼,分別簡要分析一下數據均衡功能的主線程與遷移線程的處理流程。

主線程的入口函數是gf_defrag_start,該函數主要就是使用syncop框架創建一個synctask,用於本次數據均衡的處理工作。創建synctask同步任務時,指定了實際處理函數gf_defrag_start_crawl及其完成後的回調函數gf_defrag_done,下面首先給出從gf_defrag_start_crawl函數開始的一些主要處理流程,如圖15、圖16和圖17所示。然後再列出遷移線程的主要處理流程,如圖18所示。

4.3.1.      主線程處理流程

圖15.png 

圖15 gf_defrag_start_crawl函數處理流程

1、調用syncop_lookup,查詢根目錄的相關信息,位置、元數據和父目錄等信息;

2、調用syncop_setxattr,修復根目錄的哈希分佈;

3、根據命令類型判斷,如果命令類型只是修復目錄哈希分佈,則跳過遷移文件相關函數,轉到步驟9;否則,下一步;

4、調用dht_get_local_subvols_and_nodeuuids,其內部使用了同步函數syncop_getxattr,獲取本節點參與的子卷和每個相關子卷中涉及到的節點的uuid信息,並且在每個節點上的相同子卷返回的節點uuid的順序一致;

5、調用gf_defrag_total_file_size,其內部使用了syncop_statfs,獲取本節點參與子卷的總共文件大小;

6、調用gf_defrag_total_file_cnt,其內部使用了syncop_statfs,獲取本節點參與子卷的總共文件數量;

7、調用gf_thread_create,創建一個文件計數線程,用於在數據均衡過程中統計文件遷移數量,方便用戶命令行查看;

8、調用gf_thread_create,根據節點cpu活動processor的數量,創建多個遷移線程,負責具體文件遷移工作,其入口函數爲gf_defrag_task,後面會給出該函數處理流程(圖18);

9、根據命令類型判斷,如果命令類型是開啓分層(tier),則調用tier相關處理函數,由於本文不考慮tier相關操作,在此略過;否則,下一步;

10、調用gf_defrag_fix_layout,開始進行目錄的修復與文件的爬取,這也是主線程的主要工作,下面會單獨給出該函數的處理流程(圖16);

11、在修復目錄和爬取文件完成後,調用pthread_join,等待所有遷移線程完成;

12、所有遷移線程已經完成並返回,做些清理工作,並調用gf_defrag_done,結束均衡進程。

 

根據以上流程的說明,並結合前面介紹的工作機制等內容,要理解下面給出的gf_defrag_fix_layout和gf_defrag_process_dir函數處理流程並不會很難,具體過程不再贅述。

圖16.png

圖16 gf_defrag_fix_layout函數處理流程

圖17.png

圖17 gf_defrag_process_dir函數處理流程

4.3.2.      遷移線程處理流程

圖18.png

圖18 gf_defrag_task函數處理流程

多個遷移線程同時運行,每個線程的處理流程都由gf_defrag_task函數負責,簡要說明如下:

1、獲取待遷移文件的隊列defrag->queue;

2、進入如下while循環模式;

3、判斷隊列是否爲空,如果不空,下一步;否則,轉到步驟7;

4、調用list_del_init,從隊列頭取出一個文件,並更新相關計數;

5、調用gf_defrag_migrate_single_file,該函數負責單個文件遷移的整個過程,包括判斷是否需要遷移、數據內容遷移、各種屬性遷移、特殊文件處理和遷移後的清理工作等內容,此部分內容需要讀者自行分析,不再贅述;

6、gf_defrag_migrate_single_file函數完成後,返回到步驟3;

7、判斷文件爬取任務是否完成,如果沒完成,則調用pthread_cond_wait,等待新文件遷移任務到來的通知;否則,下一步;

8、遷移任務都已完成,線程返回。

 

5. 問題與優化

儘管數據均衡功能經過了不斷的完善,已經具有了良好的性能和擴展性,同時大大加快了擴容或縮容後集羣數據均衡的進度,但仍然存在一些限制和問題,具體說明如下:

(1)數據遷移速度可進一步提升

原因是在遷移數據的時候,工作線程在讀取原始文件和寫入目標文件是串行的,如果能夠將兩者有效的分開獨立進行,則可以進一步提升遷移速度;

(2)擴容或縮容時的數據遷移量大

在增加brick或刪除brick的時候,需要對整個卷做數據均衡,這樣一來,增加或刪除很少brick時,也會觸動整個集羣均衡一次,給人一種牽一髮而動全身的感覺,並且需要遷移的數據量較大,而在OpenStack Swift的數據均衡中則採用了帶有虛擬節點的一致性哈希,可以一定程度減少數據的遷移量,因此可以考慮借鑑這種做法。

(3)數據遷移速度控制能力較弱

雖然目前命令行有三種模式(lazynormalaggressive),用於控制遷移速度,但還是屬於比較粗略的控制,當有大量文件遷移時,還是會佔用較多的系統資源,影響到存儲系統性能。

(4)代碼存在bug

例如,在GlusterFS的3.12系列之前的版本中,對分佈式EC卷做擴容後做數據遷移的時候,每組EC卷只有一個節點在遷移文件,組內其他節點並沒有參與該過程,這是和其預期工作機制是不相符的,並且影響了一部分文件的遷移。

 

上面只是列出了數據均衡目前存在一些限制,可能還有其他問題,等待讀者去發現和解決。總之,未來還是有很多工作要做的,結合GlusterFS社區的討論,列出主要內容如下:

(1)優化遷移速度,遷移數據的時候,讀文件和寫文件並行化;

(2)更精細地控制數據遷移,根據實際需要靈活地調控遷移速度;

(3)優化目錄哈希分佈,減少每次擴容或縮容後需要遷移的數據量;

(4)支持遷移暫停功能,再次開啓後可以繼續從當前暫停位置開始遷移;

(5)在數據均衡進程中增加性能模塊(xlator),提高遷移效率;

(6)修復數據均衡代碼中的bug。

6. 總結與展望

本文介紹了GlusterFS當前的數據均衡功能,內容包括數據均衡的產生背景、使用場景、基本原理、程序實現剖析、操作命令實踐、存在的問題以及需要優化的地方等,同時結合實例說明了數據均衡的工作機制。

GlusterFS數據均衡功能還在不斷的完善中,相信未來的數據均衡功能一定會更加高效和可控,並且佔用較少的系統資源。

由於時間和精力有限,文中省略了很多細節,也包括一些重要的算法和流程,期望讀者能夠給予補充,同時理解不正確的地方也在所難免,歡迎指正。

參考資料

[1] https://docs.gluster.org/

[2] http://pl.atyp.us/hekafs.org/index.php/2012/03/glusterfs-algorithms-distribution/

[3] http://staged-gluster-docs.readthedocs.io/en/release3.7.0beta1/Features/rebalance/

[4] https://github.com/gluster/glusterfs-specs/blob/master/done/GlusterFS%203.7/Improve%20Rebalance%20Performance.md

[5] glusterfs v3.12.9 source code


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