DAOS 分散式非同步對象存儲|存儲模型
概述
DAOS Pool 是分布在 Target 集合上的存儲資源預留。分配給每個 Target 上的 Pool 的實際空間稱為 Pool Shard。
分配給 Pool 的總空間在創建時確定,後期可以通過調整所有 Pool Shard 的大小(在每個 Target 專用的存儲容量限制內)或跨越更多 Target(添加更多 Pool Shard)來隨時間擴展。
Pool 提供了存儲虛擬化,是資源調配和隔離的單元。DAOS Pool 不能跨多個系統。
一個 Pool 可以承載多個稱為 DAOS Container 的事務對象存儲。每個 Container 都是一個私有的對象地址空間,可以對其進行事務性修改,並且獨立於存儲在同一 Pool 中的其他 Container。Container 是快照和數據管理的單元。屬於 Container 的 DAOS 對象可以分布在當前 Pool 的任何一個 Target 上以提高性能和恢復能力,並且可以通過不同的 API 訪問,從而高效地表示結構化、半結構化和非結構化數據。
下表顯示了每個 DAOS 概念的目標可伸縮性級別:
DAOS 概念 | 可伸縮性(數量級) |
---|---|
System | \(10^5\) Servers and \(10^2\) Pools |
Server | \(10^1\) Targets |
Pool | \(10^2\) Containers |
Container | \(10^9\) Objects |
DAOS Pool
Pool 由唯一的 Pool UUID 標識,並在稱為 Pool 映射的持久版本控制列表中維護 Target 成員身份。成員資格是確定的和一致的,成員資格的變更是按順序編號的。Pool 映射不僅記錄活躍 Target 的列表,還以樹的形式包含存儲拓撲,用於標識共享公共硬體組件的 Target。例如,樹的第一級可以表示共享同一主板的 Target,第二級可以表示共享同一機架的所有主板,最後第三級可以表示同一機房中的所有機架。
該框架有效地表示了層次化的容錯域,然後使用這些容錯域來避免將冗餘數據放置在發生相關故障的 Target 上。在任何時候,都可以將新 Target 添加到 Pool 映射中,並且可以排除失敗的 Target。此外,Pool 映射是完全版本化的,這有效地為映射的每次修改分配了唯一的序列,特別是對於失敗節點的刪除。
Pool Shard 是永久記憶體的預留,可以選擇與特定 Target 上 NVMe 預先分配的空間相結合。它有一個固定的容量,滿了就不能運行。可以隨時查詢當前空間使用情況,並報告 Pool Shard 中存儲的任何數據類型所使用的總位元組數。
一旦 Target 失敗並從 Pool 映射中排除,Pool 中的數據冗餘將自動在線恢復。這種自愈過程稱為重建。重建進度定期記錄在永久記憶體中存儲的 Pool 中的特殊日誌中,以解決級聯故障。添加新 Target 時,數據會自動遷移到新添加的 Target,以便在所有成員之間平均分配佔用的空間。這個過程稱為空間再平衡,使用專用的持久性日誌來支援中斷和重啟。
Pool 是分布在不同存儲節點上的一組 Target,在這些節點上分布數據和元數據以實現水平可伸縮性,並使用複製或糾刪碼 (erasure code) 確保持久性和可用性。
創建 Pool 時,必須定義一組系統屬性以配置 Pool 支援的不同功能。此外,用戶還可以定義將持久存儲的屬性。
Pool 只能由經過身份驗證和授權的應用程式訪問。DAOS 支援多種安全框架,例如 NFSv4 訪問控制列表或基於第三方的身份驗證 (Kerberos)。連接到 Pool 時強制執行安全性檢查。成功連接到 Pool 後,將嚮應用程式進程返回連接上下文。
如前文所述,Pool 存儲許多不同種類的持久性元數據,如 Pool 映射、身份驗證和授權資訊、用戶屬性、特性和重建日誌。這些元數據非常關鍵,需要最高級別的恢復能力。因此,Pool 的元數據被複制到幾個來自不同高級容錯域的節點上。對於具有數十萬個存儲節點的非常大的配置來說,這些節點中只有很小的一部分(大約幾十個)運行 Pool 元數據服務。在存儲節點數量有限的情況下,DAOS 可以依賴一致性演算法來達成一致,在出現故障時保證一致性,避免腦裂。
要訪問 Pool,用戶進程應該連接到 Pool 並通過安全檢查。一旦授權,Pool 就可以與任何或所有對等應用程式進程(類似 openg()
POSIX 擴展)共享(通過 local2global()
和 global2local()
操作)連接。這種集體連接機制有助於在數據中心上運行大規模分散式作業時避免元數據請求風暴。當發出連接請求的原始進程與 Pool 斷開連接時,Pool 連接將被註銷。
DAOS Container
Container 代表 Pool 中的對象地址空間,由 Container UUID 標識。
下圖顯示了用戶(I/O 中間件、特定領域的數據格式、大數據或 AI 框架等)如何使用 Container 來存儲相關數據集:
與 Pool 一樣,Container 可以存儲用戶屬性。Container 在創建時必須傳遞一組屬性,以配置不同的功能,例如校驗和。
要訪問 Container,應用程式必須首先連接到 Pool,然後打開 Container。如果應用程式被授權訪問 Container,則返回 Container 句柄,它的功能包括授權應用程式中的任何進程訪問 Container 及其內容。打開進程可以與所有對等進程共享此句柄。它們的功能在 Container 關閉時被撤銷。
Container 中的對象可能具有不同的模式,用於處理數據分布和 Target 上的冗餘,定義對象模式所需的一些參數包括動態或靜態條帶化、複製或糾刪碼。Object 類定義了一組對象的公共模式屬性,每個 Object 類都被分配一個唯一的標識符,並在 Pool 級別與給定的模式相關聯。一個新的 Object 類可以在任何時候用一個可配置的模式來定義,這個模式在創建之後是不可變的(或者至少在屬於這個類的所有對象都被銷毀之前)。
為了方便起見,在創建 Pool 時,默認情況下會預定義幾個最常用的 Object 類:
Object Class (RW = read/write, RM = read-mostly | Redundancy | Layout (SC = stripe count, RC = replica count, PC = parity count, TGT = target |
---|---|---|
Small size & RW | Replication | static SCxRC, e.g. 1×4 |
Small size & RM | Erasure code | static SC+PC, e.g. 4+2 |
Large size & RW | Replication | static SCxRC over max #targets) |
Large size & RM | Erasure code | static SCx(SC+PC) w/ max #TGT) |
Unknown size & RW | Replication | SCxRC, e.g. 1×4 initially and grows |
Unknown size & RM | Erasure code | SC+PC, e.g. 4+2 initially and grows |
如下所示,Container 中的每個對象都由一個唯一的 128 位對象地址標識。對象地址的高 32 位保留給 DAOS 來編碼內部元數據,比如 Object 類。剩下的 96 位由用戶管理,在 Container 中應該是唯一的。只要保證唯一性,棧的上層就可以使用這些位來編碼它們的元數據。DAOS API 為每個 Container 提供了 64 位可伸縮對象 ID 分配器。應用程式要存儲的對象 ID 是完整的 128 位地址,該地址僅供一次性使用,並且只能與單個對象模式相關聯。
<---------------------------------- 128 bits ---------------------------------->
--------------------------------------------------------------------------------
|DAOS Internal Bits| Unique User Bits |
--------------------------------------------------------------------------------
<---- 32 bits ----><------------------------- 96 bits ------------------------->
Container 是事務和版本控制的基本單元。所有的對象操作都被 DAOS 庫隱式地標記為一個稱為 epoch 的時間戳。DAOS 事務 API 允許組合多個對象更新到單個原子事務中,並基於 epoch 順序進行多版本並發控制。所有版本更新都可以定期聚合,以回收重疊寫入所佔用的空間,並降低元數據複雜性。快照是一個永久引用,可以放置在特定的 epoch 上以防止聚合。
Container 元數據(快照列表、打開的句柄、對象類、用戶屬性、屬性和其他)存儲在持久性記憶體中,並由專用 Container 元數據服務維護,該服務使用與父元數據 Pool 服務相同的複製引擎或自己的引擎,這在創建 Container 時是可配置的。
與 Pool 一樣,對 Container 的訪問由 Container 句柄控制。要獲取有效的句柄,應用程式進程必須打開 Container 並通過安全檢查。然後,可以通過 Container 的 local2global()
和 global2local()
操作與其他對等應用程式進程共享此句柄。
DAOS Object
為了避免傳統存儲系統常見的擴展問題和開銷,DAOS 有意將對象簡化,不提供類型和架構之外的默認對象元數據。這意味著系統不維護時間、大小、所有者、許可權,甚至不跟蹤開啟者。
為了實現高可用性和水平伸縮性,DAOS 提供了許多對象模式(複製/糾刪碼、靜態/動態條帶化等)。模式框架是靈活的,並且易於擴展,以允許將來使用新的自定義模式類型。模式布局是在對象標識符和 Pool 映射打開的對象上通過演算法生成的。通過在網路傳輸和存儲期間使用校驗和保護對象數據,確保了端到端的完整性。
可以通過不同的 API 訪問 DAOS 對象:
- Multi-level key-array API 是具有局部性特徵的本機對象介面。密鑰分為分發密鑰 (dkey) 和屬性密鑰 (akey)。dkey 和 akey 都可以是可變長度的類型(字元串、整數或其它複雜的數據結構)。同一 dkey 下的所有條目都保證在同一 Target 上並置。與 akey 關聯的值可以是不能部分修改的單個可變長度值,也可以是固定長度值的數組。akeys 和 dkey 都支援枚舉。
- Key-value API 提供了一個簡單的鍵和可變長度值介面。它支援傳統的 put、get、remove 和 list 操作。
- Array API 實現了一個由固定大小的元素組成的一維數組,該數組的定址方式是 64 位偏移定址。DAOS 數組支援任意範圍的讀、寫和 punch 操作。
相關資訊
GitHub: //github.com/storagezhang
Emai: [email protected]
華為雲社區: //bbs.huaweicloud.com/blogs/253715