本來本篇是想介紹前端組件化開發用戶界面,發現框架還未實現文件存儲,原本計劃是後續設計開發的,索性把計劃提前,所以本篇將介紹基於Raft實現分佈式的文件存儲引擎。
一. 實現思路
既然是分佈式存儲,就需要解決以下幾個關鍵問題:
- 如何將文件以多副本的形式存儲在集羣的節點上,且保證副本間的一致性?這個問題可基於Raft協議實現相應的狀態機來解決;
- 如何將大量的文件分組,即如何劃分多個Raft組?這個問題可通過在目錄元數據內保存多個Raft組信息,每個組存儲限制在64M(暫定)來解決;
- 如何存儲與管理目錄及文件的元數據?這個問題可通過實現元數據狀態機來管理,利用已實現的KV存儲引擎來存儲元數據;
- 如何保證元數據與文件數據的一致性?這個問題開始時想用已實現的EntityStore的事務引擎來解決,雖能保證強一致性但邏輯複雜,性能損失大。因此放棄了強一致性改爲保證最終一致性,元數據狀態機及文件狀態機內都有定時器來檢查不一致的狀態。
1. 元數據存儲-BlobMetaStateMachine
開始時想設計爲一個集羣對應一個BlobMetaRaftGroup,後來考慮到單個RaftGroup可能會壓力較大,所以改爲每個Application對應一個BlobMetaRaftGroup。每個元數據狀態機主要存儲以下各項信息:
- 目錄元數據:包括目錄名稱及標識,該目錄下分配了多少個Chunk,每個Chunk佔用了多少空間,隸屬於哪個RaftGroup等;
- 文件元數據:包括文件名稱及標識,該文件隸屬的目錄標識及隸屬的ChunkRaftGroup標識等;
- Chunk元數據: 包括Chunk的RaftGroup內的各個RaftNode分配在集羣的哪個節點上;
- 寫鎖數據:用於併發寫時加鎖。
確認了需要存儲哪些信息後,就需要確認如何將這些數據映射至底層的KV存儲,既要保證高效又要方便Api檢索這些元數據,經過一些嘗試後最終定爲以下方案。
目錄元數據 Key
TypeFlag | AppId | 目錄名稱UTF8編碼 |
---|---|---|
8bit | 8bit | n bit |
- TypeFlag = 0
- 注意:最後一個'/' 0x2F被替換爲0x00,以方便掃描某一目錄下所有子目錄
目錄元數據 Value
目錄Id | Chunk RaftGroup數量 | Chunk RaftGroupIds |
---|---|---|
128bit | 16bit | n * 64bit |
文件元數據 Key
TypeFlag | AppId | 目錄Guid | 分隔佔位 | 名稱UTF8編碼 |
---|---|---|---|---|
8bit | 8bit | 128bit | 8bit | n bit |
- TypeFlag = 1
- 分隔佔位始終 = 0
文件元數據 Value
文件Id | 文件大小 | Chunk RaftGroupId |
---|---|---|
128bit | 32bit | 64bit |
2. 文件存儲-BlobChunkStateMachine
根據上述設計,每個目錄下的文件分成了多個存儲組(BlobChunkRaftGroup),本來想用MemoryMapFile來實現底層Chunk存儲,但考慮到有更重要的功能要實現所以暫偷懶直接利用Linux文件系統來存儲文件,狀態機Apply文件寫命令時,將文件直接寫入節點運行時blob/ChunkRaftGroupId/目錄下。
3. 讀寫流程
- 讀流程較簡單: 發送讀元數據命令至BlobMetaRaftGroup獲取文件元數據(緩存),然後再分小塊發讀命令至目標ChunkRaftGroup獲取文件小塊數據;
- 寫流程要考慮元數據與文件數據的一致性,還要考慮在目錄下無可用ChunkRaftGroup時創建新的組,具體參考以下設計草圖:
二. 實現效果
根據以上設計在經歷了1個月的編碼後已初步實現(其中約一半時間在更改架構,拋棄了Mono依賴,改爲Hosting CoreCLR,性能提升1倍),在框架IDE內每個Application內有個"BlobStore"節點,如下圖所示可測試上傳文件,然後通過瀏覽器訪問上傳至/pub目錄內的文件(http://{地址:端口}/blob/{app名稱}/{文件路徑} eg: http://xx.xx.xx.xx:5000/blob/sys/imgs/aa.jpg)
作者簡單測試了一下通過框架WebHost下載文件的性能(測試時尚未實現緩存元數據, 虛擬機I74C8G),如下圖所示:
三. 本篇小結
本實現適用於存儲大量小文件,如業務單證的附件,或者用於OA系統作爲文檔庫。目前只是實現了基本的上傳下載功能,刪除、重命名、Chunk合併等功能尚未實現,另待將來框架實現反向索引後再實現全文搜索功能。
框架已更新,如何安裝測試請參考AppBoxFuture(一): Hello Future!(架構圖尚未更新)。如果您有問題或Bug報告,請留言或在Github提交Issue。