極光高階工程師——胡冠軍
一、背景
因UMS5.1版本當中簡訊簽名,郵件支援上傳本地圖片/支援上傳附件的產品需求,以及後續可能存在的需要大量檔案儲存的場景,所以需做一個私有云自己的檔案伺服器,並且該伺服器也要相容客戶檔案伺服器(注:客戶檔案伺服器一般都是相容S3協議的)
二、調研檔案伺服器
經過各種調研,選型和組內討論,最終決定選擇minIO
1.minIO簡介
minIO 是一個基於 Apache License v2.0 開源協議使用 Go 語言開發的物件儲存服務。它相容亞馬遜 S3 雲端儲存服務介面,非常適合於儲存大容量非結構化的資料,例如圖片、視訊、日誌檔案、備份資料和容器/虛擬機器映象等,而一個物件檔案可以從幾kb到最大5T不等。minIO 是一個非常輕量的服務,可以很簡單的和其他應用的結合,類似 NodeJS, Redis 或者 MySQL。
2.minIO優勢
相容 Amazon S3
minIO使用 Amazon S3 v2 / v4 API。
資料保護
minIO使用erasure code來防止硬體故障。即使損壞一半以上的硬碟,仍然可以從中恢復資料。
高度可用
minIO伺服器可以容忍分散式系統中高達(N / 2)-1 節點故障。
Lambda 計算
minIO伺服器通過其相容 AWS SNS / SQS 的事件通知服務觸發 Lambda 功能。支援的目標是訊息佇列,如Kafka,AMQP,以及 Elasticsearch,Redis,MySQL 等資料庫。
加密和防篡改
minIO為加密資料提供了機密性,完整性和真實性保證,而且效能開銷微乎其微。使用 AES-256-GCM,ChaCha20-Poly1305 和 AES-CBC 支援伺服器端和客戶端加密。
可對接後端儲存
除了minIO自己的檔案系統,還支援 DAS、 JBODs、NAS、Google 雲端儲存和 Azure Blob 儲存。
sdk 支援
基於minIO輕量的特點,它得到類似 Java、Python 或 Go 等語言的 sdk 支援
一致性
minIO在分散式和單機模式下,所有讀寫操作都嚴格遵守read-after-write一致性模型。
3.minIO架構圖
minIO採用去中心化的無共享架構,物件資料被打散存放在不同節點的多塊硬碟,對外提供統一名稱空間訪問,並通過Web負載均衡器或DNS輪詢(DNS round-robin)在各伺服器之間實現負載均衡。
4.minIO儲存機制
4.1 基本概念
硬碟(Drive):即儲存資料的磁碟,在 minIO 啟動時,以引數的方式傳入。
組( Set ):即一組 Drive 的集合,分散式部署根據叢集規模自動劃分一個或多個 Set ,每個 Set 中的 Drive 分佈在不同位置。一個物件儲存在一個 Set 上。
桶(Bucket):檔案物件儲存的邏輯位置,對於客戶端而言,就相當於一個存放檔案的頂層資料夾。
4.2 糾刪碼
minIO 使用糾刪碼(erasure code)和校驗和(check sum)來保護資料免受硬體故障和無聲資料損壞。 即便您丟失一半數量(N/2)的硬碟,您仍然可以恢復資料。
什麼是糾刪碼呢?它是一種恢復丟失和損壞資料的數學演算法,minIO 採用Reed-Solomon Code實現糾刪碼,它將物件拆分成N/2 資料塊和 N/2 奇偶校驗塊。這就意味著如果是 12 塊盤,一個物件會被分成 6 個資料塊、6 個奇偶校驗塊,您可以丟失任意 6 塊盤(不管其是存放的資料塊還是奇偶校驗塊),您仍可以從剩下的盤中的資料進行恢復。
4.3 Reed-Solomon Code資料恢復原理簡析
RS編碼以word為編碼和解碼單位,大的資料塊拆分到字長為w(取值一般為8或者16位)的word,然後對word進行編解碼。 資料塊的編碼原理與word編碼原理相同,後文中以word為例說明,變數Di, Ci將代表一個word。把輸入資料視為向量D=(D1,D2,..., Dn), 編碼後資料視為向量(D1, D2,..., Dn, C1, C2,.., Cm),RS編碼可視為如下(圖1)所示矩陣運算。圖1最左邊是編碼矩陣(或稱為生成矩陣、分佈矩陣,Distribution Matrix),編碼矩陣需要滿足任意n*n子矩陣可逆。為方便資料儲存,編碼矩陣上部是單位陣(n行n列),下部是m行n列矩陣。下部矩陣可以選擇範德蒙德矩陣或柯西矩陣。
RS最多能容忍m個資料塊被刪除。 資料恢復的過程如下:
(1)假設D1、D4、C2丟失,從編碼矩陣中刪掉丟失的資料塊/編碼塊對應的行。(圖2、3)
(2)由於B' 是可逆的,記B'的逆矩陣為 (B'^-1),則B' * (B'^-1) = I 單位矩陣。兩邊左乘B' 逆矩陣。 (圖4、5)
(3)得到如下原始資料D的計算公式,如下圖:
(4)對D重新編碼,可得到丟失的編碼。
4.4 以糾刪碼模式執行minIO
minIO會自動生成12塊盤,命令如下:
4.5 儲存形式
資料物件在minIO叢集中進行儲存時,先進行糾刪分片,後打散儲存在各硬碟上。具體為:minIO自動在叢集內生成若干糾刪組,每個糾刪組包含一組硬碟,其數量通常為4至16塊;對資料物件進行分片,預設策略是得到相同數量的資料分片和校驗分片;而後通過雜湊演算法計算出該資料物件對應的糾刪組,並將資料和校驗分片儲存至糾刪組內的硬碟上。
如上圖所示,假設某minIO叢集內糾刪組包含4塊硬碟,某資料物件名為MyObject,其隸屬儲存桶名為MyBucket,雜湊計算得到對應的糾刪組為Disk 1~4。那麼在Disk 1~4的資料路徑下,都會生成MyBucket/MyObject子路徑,子路徑中包含2個檔案,分別為儲存後設資料資訊的xl.json和MyObject物件在該盤上的第一個分片part.1。其中,xl表示minIO中資料物件的預設儲存格式。
5.minIO golang SDK簡單使用
以下上傳檔案的例子可以直接執行,檔案會上傳到minIO官方伺服器
三、minIO在UMS系統中的實際應用
1.應用系統架構
整個架構中,模組之間使用http協議通訊,並且每個模組的作用如下:
(1)Web/API伺服器的作用是提供UMS系統的認證和鑑權,即驗證Web客戶端或者開發者API請求介面的合法性;
(2)檔案管理伺服器的作用是提供對外操作minIO伺服器的介面,根據目前UMS系統的業務需求,只提供了獲取上傳檔案presignedURL,設定過期時間, 設定對外訪問
策略,建立儲存桶,生成下載檔案URL的功能;那麼什麼是presignedURL呢?它是物件所有者使用自己的安全憑證來建立預簽名的 URL,以授予有限時間內的上傳或下
載物件許可權,從而與其他使用者共享物件,注:即使是私有物件使用presignedURL也可以共享給他人,並且presignedURL最大有效期為7天。
其中檔案管理伺服器獲取上傳檔案presignedURL的方法直接使用了minIO官方API,當然你也可以自己實現presignedURL方法,此外,由於下載presignedURL最大保留時間為7天,不符合UMS系統業務需求,所以,檔案管理伺服器自己實現了一個生成下載URL的方法,此連結的過期時間可任意設定,但前提要把儲存桶的對外訪問策略設定為public。由此,客戶端就可以直接使用上傳presignedURL上檔案到minIO伺服器,使用下載連結直接下載檔案即可。
(3)minIO叢集作用是儲存實體檔案,該叢集採用去中心化無共享架構,各節點間為對等關係,連線至任一節點均可實現對叢集的訪問,minIO叢集前端增加了Nginx實現反向代理;minIO節點之間的通訊使用的都是rpc。此外,管理minIO伺服器除了上面提到的SDK以外,官方還提供了命令列和web頁面的形式,內容分別如下:
把Nginx代理ip和埠號或者minIO叢集中任意節點的ip和埠號輸入瀏覽器,輸入minIO的賬戶名和密碼即可登入,介面如下:
2.具體互動邏輯
首先,客戶端要請求業務伺服器(WebServer/APIServer)獲取上傳檔案的憑證(presignedURL),然後,業務伺服器響應一個上傳檔案URL和下載檔案的URL,客戶端使用上傳URL上傳檔案到檔案伺服器,使用下載URL作為請求後端的檔案引數,如傳送郵件訊息支援上傳本地圖片,上傳到後端的圖片即可使用檔案下載URL作為引數。
該方案的優點如下:
客戶端直接上傳檔案到minIO伺服器,不經過業務伺服器,減輕業務伺服器的壓力,提高可用性
資料庫伺服器只儲存檔案的下載URL,減少資料庫的儲存量
支援上傳超大檔案,比如3G以上等,硬體效能足夠的情況下,minIO伺服器單個檔案最大可達5T
上傳檔案的數量沒有限制
可以解決同名檔案覆蓋問題
可以適配任何相容S3協議的檔案伺服器,滿足不同客戶的要求
四、minIO分散式部署
minIO分散式部署架構
1.1 架構概述
minIO叢集採用去中心化無共享架構,各節點間為對等關係,連線至任一節點均可實現對叢集的訪問,這種節點間保持對等關係的設計並非最常見的分散式叢集架構。當前大多數的分散式儲存叢集,其節點往往可劃分為多類角色,例如負責連線並處理外部應用請求的訪問節點、負責儲存後設資料的管理節點、實際的資料儲存節點等。minIO與之不同,minIO叢集中的所有節點都同時承擔了多種角色,集後設資料儲存、資料儲存、應用訪問等功能於一體,真正實現了去中心化和所有節點的完全對等。其優勢在於有效地減少了叢集內的複雜排程過程以及因中心節點帶來的故障風險和效能瓶頸。
下圖minIO叢集增加了Nginx代理:
部署minIO叢集只需一條命令,但叢集中每個節點都要執行相同的命令
其中,官方推薦節點ip要連續。
1.2 minIO擴容方案
首先,minIO的極簡設計理念使得minIO分散式叢集並不支援向叢集中新增單個節點並進行自動調節的擴容方式,這是因為加入單個節點後所引發的資料均衡以及糾刪組劃分等問題會為整個叢集帶來複雜的排程和處理過程,並不利於維護。因此,minIO提供了一種對等擴容的方式,即要求增加的節點數和磁碟數均需與原叢集保持對等。
例如原叢集包含4個節點4塊磁碟,則在擴容時必須同樣增加4個節點4塊磁碟(或為其倍數),以便系統維持相同的資料冗餘SLA,從而極大地降低擴容的複雜性。如上例,在擴容後,minIO叢集並不會對全部的8個節點進行完全的資料均衡,而是將原本的4個節點視作一個區域,新加入的4節點視作另一區域,當有新物件上傳時,叢集將依據各區域的可用空間比例確定存放區域,在各區域內仍舊通過雜湊演算法確定對應的糾刪組進行最終的存放。此外,叢集進行一次對等擴容後,還可依據擴容規則繼續進行對等擴容,但出於安全性考慮,叢集的最大節點數一般不得超過32個。
minIO支援通過命令,指定新的叢集來擴充套件現有叢集(糾刪碼模式),命令列如下:
現在整個叢集就擴充套件了1024個磁碟,總磁碟變為2048個,新的物件上傳請求會自動分配到最少使用的叢集上。通過以上擴充套件策略,您就可以按需擴充套件您的叢集。重新配置後重啟叢集,會立即在叢集中生效,並對現有叢集無影響。如上命令中,我們可以把原來的叢集看做一個區,新增叢集看做另一個區,新物件按每個區域中的可用空間比例放置在區域中。在每個區域內,基於確定性雜湊演算法確定位置。
注:您新增的每個區域必須具有與原始區域相同的磁碟數量(糾刪碼集)大小,以便維持相同的資料冗餘SLA。 例如,第一個區有8個磁碟,您可以將叢集擴充套件為16個、32個或1024個磁碟的區域,您只需確保部署的SLA是原始區域的倍數即可。
對等擴容的優點和缺點如下:
優點:在於配置操作簡單易行,通過一條命令即可完成擴容。
缺點:①擴容需重啟;②擴容存在限制,叢集節點數一般不超過32個,這是由於MinIO叢集通過分散式鎖保證強一致性,若叢集節點數過大,維護強一致性將帶來效能問題。
但對於初期儲存量不是很大,並且叢集短暫停機重啟對業務影響不大的情況下,使用對等擴容即可。
注意事項
分散式minIO裡所有的節點需要有同樣的access祕鑰和secret祕鑰,即:使用者名稱和密碼
分散式minIO存放資料的磁碟目錄必須是空目錄
分散式minIO官方建議生產環境最少4個節點,因為有N個節點,得至少保證有N/2的節點才能可讀,保證至少N/2+1的節點才能可寫
分散式minIO節點時間要相同,機器配置也要都相同
分散式minIO會在每個磁碟都存一份資料檔案保證資料的可靠性與安全性
3.具體實施步驟
網上很多人部署minIO叢集都是使用單個指令碼,這在實際生產環境中很不友好,因為minIO要求叢集中每個節點都要執行相同的命令才能啟動成功,所以最好的方式是使用ansible部署minIO叢集。
3.1 安裝ansible
3.2 使用ansible部署minIO叢集
Ansible編寫的核心程式碼如下,具體細節讀者可自行百度
3.3 配置Nginx代理叢集
Nginx配置檔案內容如下:
3.4 驗證minIO叢集是否部署成功
在瀏覽器上,輸入Nginx所在伺服器的地址外加Nginx配置裡的監聽埠即可訪問檔案伺服器web頁面,部署成功的效果如下:
五、結語
以上就是UMS私有云檔案服務開發以及部署的主要內容,該方案已經得到實施驗證,如果您想搭建相容S3協議的檔案伺服器,那麼該篇文章有參考價值,當然由於時間倉促並且初期檔案儲存量不是很大,該方案也有需要優化的地方,比如想實現動態擴容機制可以採用官方聯邦擴容方式,不過這需要引入etcd,也需要更多的機器。總之,您還是需要根據具體業務場景來定,就像買鞋子不是越大越好,合腳的才是最好的。