MinIO學習筆記

探探的實踐:https://mp.weixin.qq.com/s?__biz=MzA4ODg0NDkzOA==&mid=2247487119&idx=1&sn=6e09abb32392e015911be3a1d7f066e5&source=41#wechat_redirect

一、競品調研

在這裏插入圖片描述
當前的一些開源方案,這些存儲方案裏面可以分爲兩種:

  • 一種是可以自定對象名稱的;
  • 另外一種是系統自動生成對象名稱。

我們的對象名是自己生成的,裏面包含了業務邏輯。
1、像 FS 就是國內大佬開源的一個分支存儲,但是因爲不能自定義文件名所以不合適。
2、還有像領英的 Ambry、MogileFS 其實都不能自定對象名的,所以是不合適的。
3、LeoFS 對我們來說不是很可控,所以不合適。
4、TFS 是淘寶開源的,但是目前已經很少有人維護它並且也不是很活躍,所以當時就沒有考慮。
5、ceph 是一個比較強大的分佈式存儲,但是它整個系統非常複雜需要大量的人力進行維護,對我們的產品不是很符合,所以暫時不考慮。

二、初識MinIO

1、MinIO的架構

在這裏插入圖片描述
左邊是 MINIO 集羣的示意圖,整個集羣是由多個角色完全相同的節點所組成的。因爲沒有特殊的節點,所以任何節點宕機都不會影響整個集羣節點之間的通信。
通過 rest 跟 RPC 去通信的,主要是實現分佈式的鎖跟文件的一些操作。

右邊這張圖是單個節點的示意圖,每個節點都單獨對外提供兼容 S3 的服務。

2、MinIO概念介紹:Drive和Set

  • Drive:可以理解爲一塊磁盤
  • Set:一組Drive的集合
    • 一個對象存儲在一個Set上
    • 一個集羣劃分爲多個Set
    • 一個Set包含的Drive數量是固定的
      • 默認由系統根據集羣規模自動計算得出
      • MINIO_ERASURE_SET_DRIVE_COUNT
    • 一個SET中的Drive儘可能分佈在不同的節點上

在這裏插入圖片描述

上圖中,每一行是一個機器節點,這裏有32個集羣,每個節點裏有一個小方塊,我們稱之爲Drive,Drive可簡單地理解爲磁盤。一個節點有32個Drive,相當於32個磁盤。
Set是另外的概念,Set是一組Drive的集合,所有紅色標識的Drive組成了一個Set。

一個對象最終是存儲在一個Set裏面的。

3、MinIO核心流程

3.1、數據編碼

Erasure Code:冗餘編碼

  • 將一個對象編碼成若干個數據塊校驗塊
  • Reed-Solomon算法
  • 低冗餘、高可靠

MinIO的編碼方式,我們簡稱爲Erasure Code碼,是通過算法還原數據的方法。MinIO使用Reed-Solomon算法,該算法把對象編碼成若干個數據塊和校驗塊。
爲了表述方便,把數據庫和校驗塊統稱爲編碼塊,之後我們可以通過編碼塊的一部分就能還原出整個對象。

在這裏插入圖片描述
如上圖,如我們所知,一個對象存儲在一個Set上面,這個Set包含16個Drive,其中灰色的一半是數據庫,橙色的一半是校驗塊,這種方式最多能忍受一半的編碼丟失或損壞。所有編碼塊的大小是原對象的2倍,跟傳統多副本存儲方案相比,他只冗餘存了一份,但可靠性更高。

接下來講Bit Rot Protection,直譯就是腐爛。它只物理設備上的一些文件細微的損壞,還沒有被操作系統所硬件所察覺,但是他已經損壞了。
Bit Rot Protection:

  • HighwayHash

MinIO把之前的編碼塊進行 HighwayHash 編碼,最後要校驗這個編碼,以確保每個編碼是正確的。

基於 Erasure CodeBit Rot Protection 這兩個特性,所以MinIO的數據可靠性做的高。

另外,MinIO提供了一個管理工具,可以對所有編碼塊進行校驗,如果發現編碼塊有問題,再去修復它。

3.2、存儲形式

在這裏插入圖片描述
上圖直觀地展示了每個節點上的數據存放形式。所有對象的編碼塊和meta信息,最終是以目錄和文件的形式,存儲在文件系統上的。

比如My Bucket就是在所有節點的頂級目錄創建了對應的目錄叫My Bucket。然後當我們上傳一個對象的時候,就會在這個對象所對應的Set上面創建一個目錄叫My Object,之後把所有編碼塊的數據跟meta信息都保存在此目錄下面,這就是MinIO的真實存儲數據的方式。

meta數據是json文件,編碼塊是part.1文件。黑色的右圖是meta信息示例圖,裏面除了包含正常的meta信息外,還包括了怎樣做ec編碼,以便之後可以解碼出來。

3.3、上傳和下載流程

1、上傳流程:
1)先根據對象名去做一個Hash,計算出對應的Set,然後來創建臨時目錄。創建臨時目錄的目的是爲了確保數據強一致性,所以中間數據都會被寫入到這個臨時目錄裏(直到所有數據寫完後,再統一把目錄寫入到最終的路徑上)
2)接下來讀數據編碼,每次最多讀10M的數據處理,然後做編碼,再被寫入到磁盤上,循環的過程就是把數據保存下來。
3)數據保存完後,再寫meta信息。
4)然後挪到最終的位置上,刪除臨時目錄。

2、讀取流程:
1)先根據對象名做Hash,找到對象對應的Set
2)然後去讀取meta信息,通過meta信息來獲得編碼的方式,然後去解碼。它是以10M數據做EC編碼,讀的時候也是逐個part解析,每個part給他做解碼,然後寫入到一個io write裏面。
備註:我們剛剛說了,做EC碼時,只要一半的編碼塊就能還原整個對象,所以讀meta時讀了N份,但是讀數據時只要讀N/2就可以了。

四、部署和擴容

1、如何部署

#啓動一個12個節點的MinIO集羣,每個節點有12個Drive
minio server http://10.3.1.{1...12}/data/{1...12}

MinIO的部署默認不需要配置文件,幾秒鐘就可以把集羣搭建起來,把簡潔做到了極致。

2、MinIO壓測

可採用 cosBench 工具做壓測,cosBench是專門對對象存儲做壓測的工具。

在12個節點,每個節點12個盤,混合讀寫64KB。
結果是:
1、讀請求:4千QPS,響應的平均延遲是35毫秒;
2、寫請求:900 QPS時,平均響應時間是45毫秒。

五、MinIO的侷限

侷限1、搭建集羣后,不允許擴容

MinIO一旦集羣搭建成功後,就不可以更改集羣節點數。因爲存在在MinIO的對象到底存儲在哪個Set,是通過名字做Hash去找的,一旦節點數變了落點就錯亂了。

侷限2、大集羣最大節點數爲32

MinIO實現了一個峯值鎖叫DSync。它在節點數量少時,性能非常高;但節點數量過多時,性能就下降了。功能實現的最大節點就是32,所以導致MinIO單個集羣的最大節點數也是32。

官方回覆是,他們十年做GlusterFS的經驗看,一個超大的集羣是難以維護的,尤其是宕機之後的恢復時間也特別長,所以他們在做MinIO的時候一個核心設計理念就是簡單,易於維護。

擴容方案

1、可同時向多個集羣寫入
2、當集羣容量達到閾值,從寫集羣中剔除,變成只讀
3、讀取的時候,根據編碼到文件名上的集羣信息,從而路由到正確的集羣。

MinIO本身提供一個叫聯合模式的方式來組建集羣,但是要額外引入其他依賴。可以考慮在LB層根據其請求裏面的一些header信息做流量轉發。

當配置多個集羣的時候,可以先從配置中獲取可用的集羣,再從LB上根據請求的header信息,可控制向哪個集羣寫。當某個集羣的容量達到閾值時,可以從配置中剔除該集羣,把他變成只讀集羣。讀取的時候把集羣ID或信息碼編碼到文件名上去,這樣可以通過解析文件名就能獲取到對應的集羣。

六、關於IO

IO有Buffered IO 和 Direct IO:

  • buffered IO:在讀寫的時候回經過一個page Cache
  • Direct IO:是繞過page Cache,直接對磁盤操作,所以性能會差些。

再回顧下MinIO的寫入流程:MinIO數據最終的形式是寫入文件系統的文件,也就是隨機寫的。隨機寫的性能肯定不如順序寫。
其次,EC編碼在低冗餘情況下是高可靠的,但同時也讓他寫入數量變多了,基本上一個對象寫入需要做2N次操作,其實N次是數據的操作,N是meta的操作。基於上述原理,可總結出下述優化方案:

優化方案1、小文件合併成大文件

小文件合併成大文件,只需要把底層文件的部分稍微改一下,把原來隨機寫的小文件改成順序寫的大文件,這樣就可以利用page cache來提供磁盤的能力。

具體實現:預先打開一個文件,分配一個固定的空間,目的是保證文件在磁盤上真是存儲的數據是連續的。當寫文件的時候,就給加鎖,保證數據寫入,因爲這些原因,小文件的索引需要保存下來,所以我們引入了一個levelDB像大文件的ID和size的一些東西,之所以採用level DB是因爲他的性能非常好。

接下來看MinIO的讀流程:它主要發生在IO的地方有兩個:一個是meta信息,然後再讀data的時候,至少從N/2個節點上讀取。每一次讀取meta或者data的時候包括兩部分:第一個從levelDB中讀取索引,從大文件中讀取對應的數據。

然後我們針對這個做了一個優化方案,我們把meta信息,因爲meta信息沒多少,我們把他壓縮到level DB裏,直接讀就行了,不用讀索引了。

再回顧下MinIO的讀流程:
1、從N個節點上讀取meta信息
2、至少從N/2個幾點上讀取data
3、每一次讀取的時間包括兩部分:
- 從level DB讀取索引
- 從大文件中讀取對應的數據
4、併發讀的最終時間取決於最長的一個

優化方案總結

1、將meta信息壓縮後,直接存入level DB,減少一組IO
2、將level DB存在性能更高的SSD
3、降低單個Set的Drive數量

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