分散式檔案系統 .get (V2)
2018年9月28號,我估計會記得很久這一天,因為那天剛剛好是我來西廠的一週年,那天剛剛好是農曆生日,剛剛好那天晚上我挖了一個大坑,跟遣懷師兄和小美姐姐一起填坑到深夜,真是難忘的一天。。。。。
過去的這一年,估計是畢業這幾年來比較艱難的一年,畢竟到了新環境,新地方,附近全都是優秀的人,第一次接觸網際網路產品,第一次接觸零售這個行業。但幸運的是我慢慢上手了,以至於很多人其實都不相信其實我僅僅來了一年。來到這裡其實我第一個能說上的,就是Owner感,也不知道是為啥,從畢業開始無論做哪個專案,我都沒把它們看成是工作,我都把它們看成自己的崽,都是看著它一步一個跟頭成長起來的。
看著它不進步了,會想著去找人想辦法幫它成長一把。
看著它踩坑了,會想著拉它一把。
看著它走路不穩,會想著怎麼幫它健壯一下自己。
看著它闖禍了,會想著怎麼幫它擦一下屁股。
這估計就是最大的收穫吧,它的成長就是我的成長。
進入正題吧,今天給你們帶來了新一版的分散式檔案系統,當然這依然是一個KV形式的純記憶體分散式檔案系統。能做到什麼能力呢?很方便的水平擴容(水平收縮現在還沒做),比較基礎的負載均衡,比較基礎的檔案檢查,職責分離,能用 ls/put/delete/get 這些基礎檔案操作。
實現的基礎論文還是 Google File System,程式碼都在github上,可以自己下載下來。
https://github.com/CallMeDJ/BigBananaFileSystem.git
現在聊聊怎麼啟動這套架構。
啟動Master
Master 作為整個叢集的核心管理單元,需要在第一步驟就起來,Master 承擔了檔案元資料的管理,ChunkServer的負載均衡,ChunkServer 垃圾回收,ChunkServer 檔案檢查 等核心能力,是一個一旦不提供服務,整個叢集就宕機的存在,當然一般為了穩定會做主備容災,我在這裡沒做。
直接跑一下 bfs.server.MasterServer ,啟動後MasterServer將會啟動一個路徑為 rmi://127.0.0.1:8888/master 的 rmi 服務,用來提供給叢集中的其他及進行通訊。
跑完之後我們會看見。
嗯,看見這個我們就認為穩了,Master 已經起來了,成功了一半。
啟動ChunkServer
GFS中,將每一個檔案片段叫為一個 Chunk (GFS會將大檔案切分為大小一致的塊名為 Chunk),所以我們將儲存管理這些 Chunk 的伺服器叫 ChunkServer。
我們的啟動類路徑是 bfs.server.ChunkServer ,這個類啟動有三個入參,分別是 (ip,埠,最大容量),這三個入參可以讓我們非常方便地啟動任意數量的 ChunkServer 進行水平擴容,當然我們專案裡建議的最小服務數量是3個,不然所有的檔案都會堆積在一個服務裡面。
啟動成功後,我們會看到,ChunkServer 的console 會提示,ChunkServer 自己提供了一個路徑為 rmi://127.0.0.1:7081/chunk_server 的 rmi 服務,而且已經註冊到了我們前端提供的master服務上。
這時候我們在master 的console 裡面,也能看到我們的ChunkServer 成功註冊到 Master 的提示。
擴充套件ChunkServer
為了實驗效果,我們把ChunkServer 擴充套件到4臺,埠和容量分別為 7080(50byte 容量) / 7081(75byte容量) / 7082(100byte容量) / 7083(200byte容量) 。
一個一個啟動,全部啟動完之後,在 master 上可以看到下面的日誌,不需要做其他特別的操作,能看到這些這些代表已經啟動並且擴容完成
啟動 Client
Client 的入口類為 bfs.server.BFSClient ,沒有特殊的引數。主要流程是請求master進行資料讀取,master 獲取資料所有的chunk塊的元資料,然後把資料塊chunk的位置及 chunkserver 的 ip 和埠給到client,由 client 直接跟 chunkserver 通訊進行資料獲取。
啟動完之後能看到下面的操作提供,則表明client已經啟動成功。
put一大批資料
我們在Client的Console敲命令列可以對檔案系統進行基礎的操作,比如放置檔案 。put mytexstt /tmp/banana/trace2.log 等。
這時候我們可以看到 master 上也有儲存成功的訊息。
我們敲命令列 ls /tmp/banana ,也可以看到檔案列表。
同時我們在各個ChunkServer 也能看到檔案儲存的md5值,完整容量以及已用容量。
PS:關於這裡的負載均衡,大家可以通過對比幾個 ChunkServer 的增長速度,增長基本是均衡的,不會堆積在某個機器上,最終所有機器基本都被佔滿,已佔滿的機器不會再提供儲存服務,除非檔案被回收。
刪除資料
比如我們想刪除 trace10.log,我們可以這樣敲命令 。
delete /tmp/banana/trace10.log
這時候Master 會把 trace10.log 檔名變更為 trace10.log.delete ,然後通過垃圾回收機制進行回收,我們可以在 Master 上看到這麼兩行日誌。
第一行是代表檔案在邏輯層面已經被刪除,第二行代表垃圾回收機制已經把檔案從元資料和 ChunkServer 上都進行了物理刪除。我們可以從各個 ChunkServer 上看到,被切割的檔案塊也都被逐一刪除,並且空間已經迴歸。
7080機器
7081機器
7082機器
7083機器
從這裡我們可以看到,檔案被切割成了兩個塊,而且複製了三個副本,儲存在四臺機器上,並且 ChunkServer 對這些檔案的實際內容以及組織形式完全無感知。
關於檔案檢查恢復
機制已經實現了,但目前還沒有找到很好的測試方法。基本邏輯就是檢查Master上儲存的md5跟ChunkServer檔案提供的md5進行對比,如果不一致那肯定是檔案出現了問題,將會對ChunkServer 上的檔案塊進行刪除,並複製其他 ChunkServer 的合法的檔案,如果三份都丟失那檔案就真的丟失了。
好了,關於分散式檔案系統的操作介紹就都在上面了,現在我們聊聊細節。
關於註冊
註冊是由 ChunkServer 呼叫 bfs.service.IMasterService#registerChunkServer 進行服務註冊的。
關於Client的命令
命令是通過命令控制中心 bfs.command.CommandCenter#execute 進行命令的解析,分發,呼叫,返回的,所有支援的命令都實現了bfs.command.Command 介面,並且在初始化的時候註冊到控制中心中,控制中心持有了 包括 Master 和 所有 ChunkServer 的懶載入單例模式控制代碼,可以非常方便地訪問到叢集所有機器的服務。
關於put
主要實現在 bfs.service.impl.BFSMaster#put ,主要邏輯是
1、先對檔案進行切分,產生 Chunk並儲存檔案的源資料。
2、每一個塊獲取N個需要的可用伺服器,並且對伺服器容量進行提前佔用,防止檔案儲存過程中的耗時導致超量儲存導致磁碟容量溢位。
3、 對檔案進行儲存,並且儲存Chunk 所在的伺服器。
4、對伺服器佔用進行解除。
這裡獲取可用伺服器實現了針對伺服器負荷進行排序,優先獲取負荷比較小的機器,當然如果機器數量本來就很小,比如我們這裡只有4臺,基於檔案複製的基礎要求(檔案副本不能全部儲存在同一個機器上),會發現一些負荷比較高的機器也會承擔檔案儲存服務。
關於get
get 實現比較簡單,只要一個Chunk一個Chunk進行查詢,查詢到任何一個可用的伺服器就直接拿,然後對結果進行順序拼裝即可。
好了,BFS講解大概就到這裡了BFS系統原始碼的閱讀順序可以參照這個,主要看一個檔案的放置,一個檔案的獲取,一個檔案的刪除,這三個看完基本就理解了。
bfs.command.CommandCenter 所有操作的控制封裝,是 Client 操作的媒介。
bfs.service.IMasterService Master 提供的所有能力的介面
bfs.service.IChunkServerService ChunkServer 提供的所有能力的介面。
再安利一下 https://github.com/CallMeDJ/BigBananaFileSystem.git
再PS:今天我陽曆生日,祝我生日快樂。