Go 語言實現單體對象存儲
【導讀】對象存儲是什麼?本文介紹了對象存儲的基本概念並實現了一個單體對象存儲。
對象存儲
基本概念
主流存儲類型分爲三種:塊存儲、文件存儲以及對象存儲
-
NAS(文件存儲):Network Attached storage, 提供了存儲功能和文件系統的網絡服務器,客戶端可以訪問 NAS 上的文件系統,還可以上傳和下載文件,使用協議:SMB、NFS 以及 AFS 等網絡文件系統協議,對於客戶端來說就是網絡上的文件服務器。
-
SAN(塊存儲):Storage Area Network, 和 NAS 的區別就是 SAN 只提供了塊存儲,而把文件系統抽象給客戶端來管理,使用協議:Fibre\Channel、iSCSI\ATA over Ethnet 和 HyperSCSI,對於客戶端來說就是一塊磁盤,可以對其格式化,創建文件系統並掛載。
-
對象存儲:對象指的是面向對象,集合了塊存儲和文件存儲的優點,擁有訪問速度快、容量大等特性。並且容易搭配雲計算,是一種新的網絡存儲架構。
對象存儲系統 (Object-Based Storage System) 是綜合了 NAS 和 SAN 的優點,同時具有 SAN 的高速直接訪問和 NAS 的數據共享等優勢,提供了高可靠性、跨平臺性以及安全的數據共享的存儲體系結構。
爲了更好的說明三者的差異,我打個比方,假設有三個人想從 A 地到 B 地,現在有三種交通方式。甲選擇轎車、乙選擇公共汽車、丙選擇地鐵。塊存儲類似於轎車,速度快,但是容量小(轎車只能乘坐幾個人);文件存儲類似於公共汽車,速度慢(公共汽車有站點和紅綠燈需要考慮),但是容量較大(能多坐不少人);對象存儲類似於地鐵,速度快,容量大。
不同的數據管理方式
-
NAS,數據是以一個個文件的形式管理的。
-
SAN,數據是以數據塊的形式管理的,每個數據塊都有自己的地址,沒有額外的背景信息。
-
對象存儲,數據是以對象的方式管理,一個對象包括:數據、元數據、全局標識符。
對象的數據通常是無結構的數據,比如:圖片、視頻或文檔等;對象的元數據則指的是對象的相關描述,比如:圖片的大小、文檔的擁有者等;對象 id 則是一個全局的唯一標識符,用來區分對象的。
不同的訪問數據方式
-
NAS,通過 NFS 等網絡協議訪問某個遠程服務器上存儲的文件
-
SAN,通過數據塊的地址訪問 SAN 上的數據塊
-
對象存儲,通過 REST 網絡服務訪問對象
對象存儲,訪問對象的方式很方便,是通過 REST 接口對對象進行操作,用 HTTP 動詞(GET、POST、PUT、DELETE 等)描述操作。除此之外,還有一種訪問方式,就是使用各大雲商提供的客戶端去操作對象。
比如:Amazon 的 s3cmd、阿里雲的 osscmd/ossutil、騰訊雲的 coscmd 等。
對象存儲優缺點
先說優點,之前大概也提了下:
-
可擴展性高:對象存儲能夠擴展數十乃至數百 EB 的容量,能夠充分利用高密度存儲;
-
效率高:扁平化結構,不受複雜目錄系統對性能的影響;
-
無需遷移:對象存儲是一種橫向擴展系統,隨着容量的增加,數據根據算法自動分佈於所有的對象存儲節點;
-
安全性高:對象存儲通常憑藉 HTTP 調用對象存儲本身提供的認證密鑰來提供數據訪問;訪問方便:不光支持 HTTP(S) 協議,採用 REST 的 API 方式調用和檢索數據,同樣增加了 NFS 和 SMB 支持;成本相對低:與塊存儲方式相比,對象存儲是最具成本效益的數據存儲類型,並且與雲計算搭配,把對象存儲的這一特性發揮的淋漓盡致。
再提缺點:
-
最終一致性:由於不同節點的位置不同,數據同步時可能會有一定時間的延遲或者錯誤;
-
不易做數據庫:對象存儲比較適合存儲那些變動不大甚至不變的文件,而對於像數據庫這種需要直接與存儲裸盤相互映射的應用,還是塊存儲更合適。
單體對象存儲架構實現
單體對象存儲架構
go 語言實現
package main
import (
"io"
"net/http"
"os"
"log"
"strings"
)
func main() {
http.HandleFunc("/objects/",Handler)
println("server...")
log.Fatal(http.ListenAndServe("127.0.0.1:8006", nil))
}
func Handler(w http.ResponseWriter, r *http.Request){
println(r)
m := r.Method
if m == http.MethodPut{
Put(w,r)
return
}
if m == http.MethodGet{
Get(w,r)
return
}
w.WriteHeader(http.StatusMethodNotAllowed)
}
func Put(w http.ResponseWriter,r *http.Request){
//C:\Users\Administrator\go\src\awesomeProject\test_file
f,e := os.Create(("C:/Users/Administrator/go/src/awesomeProject/test_file"+"/objects/"+strings.Split(r.URL.EscapedPath(),"/")[2]))
if e != nil {
log.Println(e)
w.WriteHeader(http.StatusInternalServerError)
return
}
defer f.Close()
io.Copy(f,r.Body)
}
func Get(w http.ResponseWriter,r *http.Request){
f,e := os.Open(("C:/Users/Administrator/go/src/awesomeProject/test_file"+"/objects/"+strings.Split(r.URL.EscapedPath(),"/")[2]))
if e != nil {
log.Println(e)
w.WriteHeader(http.StatusNotFound)
return
}
defer f.Close()
io.Copy(w,f)
}
詳解
main 函數,註冊一個 HTTP 處理函數並開始監聽端口。
http.HandleFunc
的作用是註冊 HTTP 處理函數 Handler,如果由客戶端訪問本機的 HTTP 服務且以 “/objects/” 開頭,那麼請求將由 Handler 負責處理。
http.ListenAndServer
正式監聽端口,正常情況下會一直監聽,非正常情況下,log.Fatal 會對於錯誤並退出程序。
http.HandleFunc("/objects/",Handler)
println("server...")
log.Fatal(http.ListenAndServe("127.0.0.1:8006", nil))
Handler 函數,HTTP 中最重要的請求和響應 Response,Request 爲參數,根據客戶端不同的請求方式,執行不同的處理函數:Put 函數與 Get 函數。
func Handler(w http.ResponseWriter, r *http.Request){
println(r)
m := r.Method
if m == http.MethodPut{
Put(w,r)
return
}
if m == http.MethodGet{
Get(w,r)
return
}
w.WriteHeader(http.StatusMethodNotAllowed)
}
Put 函數,r.URL 變量記錄 HTTP 請求的 URL,EscapedPath 方法用於獲取結果轉義以後的路徑部分,該路徑形式是:/objects/<object_name>
,然後 strings.Split 函數功能是分割/objects/\<object\_name>,
分割爲 "“、”objects"、<object_name>
, 去數組的第三個元素就是<object_name>
,os.Create 在本地文件系統的根存儲目錄創建同名文件 f,創建成功將 r.Body 用 io.Copy 寫入文件 f。
func Put(w http.ResponseWriter,r *http.Request){
//C:\Users\Administrator\go\src\awesomeProject\test_file
f,e := os.Create(("C:/Users/Administrator/go/src/awesomeProject/test_file"+"/objects/"+strings.Split(r.URL.EscapedPath(),"/")[2]))
if e != nil {
log.Println(e)
w.WriteHeader(http.StatusInternalServerError)
return
}
defer f.Close()
io.Copy(f,r.Body)
}
Get 函數同 Put 函數類似。此文爲分佈式對象存儲 - 原理、架構及 Go 語言實現第一章總結
轉自:- 零
cnblogs.com/-wenli/p/11434347.html
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/XD0gChDdCFCiU4fxtiFfow