1. 程式人生 > >Openck_Swift原始碼分析——新增、刪除裝置時演算法詳細的實現過程

Openck_Swift原始碼分析——新增、刪除裝置時演算法詳細的實現過程

1 初始加入裝置後、上傳Object的詳細流程 

前幾篇部落格中,我們講到環的基本原理即詳細的實現過程,加入我們在初始建立Ring是執行例如以下幾條命令:

•swift-ring-builder object.builder create 5 3 1   • swift-ring-builder  object.builder  add z1-127.0.0.1:6010/sdb1 100    
swift-ring-builder  object.builder  add z2-127.0.0.1:6020/sdb2 100  swift-ring-builder  object.builder  add z3-127.0.0.1:6030/sdb3 100  swift-ring-builder  object.builder  add z4-127.0.0.1:6040/sdb4 100 
  swift-ring-builder  object.builder  rebalance 

上面幾條命令語句中,黑色的為初始建立Ring。綠色部分為向Ring中加入裝置,四個裝置分別位於不同的Zone中。且權重是一樣的。加入完裝置後須要對Ring進行平衡,以便得到replica2part2dev_id。當中關於create add rebalance方法的詳細實現過程請參考OpenStack_Swift原始碼分析——Ring的rebalance演算法原始碼詳細分析OpenStack_Swift原始碼分析——建立Ring及加入裝置原始碼演算法詳細分析

兩篇文章。

平衡後得到的replica2part2dev_id 例如以下圖所看到的:

             

                                                            圖1 初始平衡Ring後 replica2part2dev_id的對映

上圖中第一行為分配編號(在create時輸入的power為5。故為32個分割槽)。三個list分別代表了三個備份。上圖中一個裝置又同一時候相應多個不同的分割槽,例如以下圖所看到的:

                                                                                                                               

                                        圖 2 裝置反對映分割槽

結合圖1和圖2。一個裝置相應讀個分割槽,這些在儲存資料時,能更好的解決平衡性問題。

在得到了replica2part2dev_id 後,如今我們向叢集中存入一個物件。其步驟例如以下所看到的:

                                                                                                                                             

                                                 圖3 存入一個物件

向叢集中存入物件的流程例如以下圖所看到的:

                                                    

                                                                 圖4  存入物件的流程

 存入物件時,首先依據物件的名稱(account/container/object),計算其hash值。的到hash值後,取hash值的前四位元組,且向右移動32-power位得到當前object相應的分割槽號。如15,得到分割槽號後。利用分割槽號到replica2part2dev_id中找到此分割槽相應的三個裝置的Id,如圖1所看到的的裝置ID為3 1 4 。依據這三個裝置的ID,到devs中找到詳細的裝置,依據裝置的IP。port已經儲存檔案的磁碟所掛載的目錄,如sdb1。

將資料存如裝置中。資料存入裝置中的目錄結構為srv/node/sdb1/objects/15/hash值後位/hash/.data檔案。當中15為分割槽號,所以檔案右移動得到的分割槽號為15的在該裝置中都存入此目錄下。

2 新增裝置

假如系統執行了一段時間後。因須要儲存很多其它的物件,現須要對系統進行擴充套件,例如以下。我們如今新增一個裝置:

swift-ring-builder object.builder add z1-127.0.0.1:6050/sdb5 100

在zone1裡面右添加了一個裝置,其權重仍為100。加入裝置後,每個裝置的part_wanted值會變化,之前被分配的裝置。會因新加入裝置後其會超出其先須要的part_wanted故須要把他們收集回來,分配給新新增的裝置,收集的詳細演算法實現請參見我前幾篇部落格,裡面有詳細的介紹。加入裝置後,又一次對Ring進行平衡,平衡後replica2part2dev_id例如以下圖所看到的:

                  圖5 加入裝置後對映的變化

如上圖(圖中紅線上部分為加入裝置後的新對映,紅線下部分為沒加入裝置前的對映)所看到的,再加入了裝置後。被收集的分割槽是從第一個備份(第一行)先開始收集。假設第一個備份都被收集完,則再從第二個備份開始收集。如今僅僅加入了一個裝置。不會收集到第二個備份的分割槽,故如綠框中所看到的後兩個分割槽中分割槽所相應的裝置ID都沒有變化。圖中小紅框和小綠框中所看到的的,第一次平衡和新加入一個裝置後平衡的分割槽15所相應的裝置Id 當中一個由3變為5。

這樣的變化,資料的一致性是怎樣保證的呢?為保證因又一次移動平衡而帶來的分割槽和裝置對映的變動,Replicator在保證資料的一致性方面起到至關關鍵的資料。

由於Replicator這個守護程序在每個server上都有執行。故對於裝置3 。它首先依據分割槽目錄的名字獲得分割槽號然後利用Ring類對外通過的方法。得到此分割槽相應的裝置,此時它發現新的replica2part2dev_id中沒有了其本身。這時它會把目錄名為15及其下的全部檔案都刪除。而對於分割槽15所相應是新裝置5,它是怎樣得到這些檔案的呢?我們知道,Swift資料的同步是基於推送模式的。也就是4和3 會把其目錄下的檔案推送給裝置5。比方裝置4,其Replicator,在獲得分割槽15所相應的裝置後,和3對照,發現沒有檔案不同,故不推送資料,而發現5下沒有分割槽15所相應的內容,故其須要將自己分割槽15所相應的檔案推送給它,裝置3也是相同的原理。

3 刪除裝置

叢集又執行了一些時間。當中有些裝置。由於執行時間較長。裝置老化,現須要將其從叢集刪掉,Swift裝置的刪除,不是直接的物理刪除,先將其weight設定為0,當其weight變為0後,其它的裝置的part_wanted就好變大,故在rebalnace時須要先把裝置1(加入刪除裝置1)所相應的分割槽都收回,然後再又一次分配給其它分割槽。

這個過程中replica2part2dev_id變化例如以下:

  

                                                                        圖6 刪除裝置後replica2part2dev_id的變化

如圖6所看到的(綠線上方為刪除裝置後的新對映,綠線和和藍線之間為沒有刪除裝置前加入裝置後的分割槽對映。最底下為起初的對映)裝置1所相應的全部分割槽都被收集了。而每個分割槽所相應的新的裝置都會經過其它兩個裝置,來將他們檔案下的物件推送給新對映的裝置。