weedfs文件使用記錄

源碼目錄結構

核心模塊

  • weed 入口目錄
  • weed/weed_server 入口目錄與HTTP服務相關
  • topology 核心模塊,主要包括 【DataCenter, Rack, DataNode】 三層拓撲結構。
  • storage 核心模塊,主要包括【Store, Volume, Needle】這三大塊存儲相關的源碼。

輔助模塊

  • sequence 負責FileID的全局有序生成
  • filer 提供支持 HTTP REST 操作的文件服務器,其實就是基於 leveldb 把文件名和目錄結構存儲起來。
  • stats 和操作系統內存和磁盤使用狀況有關的模塊
  • operation 由protobuf生成的代碼們
  • proto 存放protobuf的描述文件
  • glog 日誌模塊
  • images 圖片服務
  • util 工具函數
  • tools 工具,暫時只有一個讀索引的文件。

多數據節點維護之 Topology

topology 整個模塊最核心的數據結構是三個:

  • DataCenter
  • Rack
  • DataNode

topology 是樹狀結構,DataNode 是樹的葉子節點, DataCenter 和 Rack 是樹的非葉子節點, DataCenter 是 Rack 的父母節點。 如下圖

 DataCenter | | ------------------ | | | | Rack Rack | | ------------ | | | | DataNode DataNode

也就是在 MasterServer 維護的拓撲結構裏, 是把 VolumeServer 的相關信息存儲在 DataNode 裏, 所以在代碼裏面可以看到如下:

dc := t.GetOrCreateDataCenter(dcName) rack := dc.GetOrCreateRack(rackName) dn := rack.FindDataNode(*joinMessage.Ip, int(*joinMessage.Port))

每次查找對應的DataNode,都需要從 DataCenter -> Rack -> DataNode 依次找下去。

數據存儲

理解Fid

curl -F "file=@/tmp/test.pdf" "127.0.0.1:9333/submit" {"fid":"1,01f96b93eb","fileName":"test.pdf","fileUrl":"localhost:8081/1,01f96b93eb","size":548840}

其中 "fid":"1,01f96b93eb" 就是 Fid,Fid 由三個部分組成 【VolumeId, NeedleId, Cookie】 組成。

  • VolumeId: 1 32bit 存儲的物理卷的Id 
  • NeedleId: 01 64bit 全局唯一NeedleId,每個存儲的文件都不一樣(除了互爲備份的)。
  • Cookie: f96b93eb 32bit Cookie值,爲了安全起見,防止惡意攻擊。

其中 VolumeId 是由 MasterServer 分配給 VolumeServer, 每個 VolumeServer 都維護個 n 個 Volume , 每個 Volume 都有一個專屬 VolumeId,之後會細說。 Needle 屬於 Volume 裏面的一個單元,後續說。

Volume

type Volume struct { Id VolumeId dir string Collection string dataFile *os.File nm NeedleMapper readOnly bool SuperBlock accessLock sync.Mutex lastModifiedTime uint64 //unix time in seconds }
  • VolumeId 通俗易懂,比如 "fid":"3,01f9896771" 裏面逗號前面的 3 就是 VolumeId 。
  • dir 就是該 Volume 所在的目錄,
  • Collection 很有用,每個 Volume 只能對應同一個 Collection,不同 Collection 的圖片存儲在不同 Volume,後面會講到。
  • 所以同一個 Volume 只能針對某一個 Collection ,而 同一個 Collection 的圖片可能分佈在不同的 Volume。 dataFile 就是對應的文件句柄。
  • nm NeedleMapper 看上去像是個 map ,其實是個列表,包含多個 Needle ,後面會講到。
  • readOnly 是否只讀
  • SuperBlock 超塊,後面會講到。
  • accessLock 互斥鎖
  • lastModifiedTime 最近修改時間

以上最關鍵的兩個點就是 SuperBlock 和 NeedleMapper , 這兩者在文件中佈局如下:

+-------------+ |SuperBlock | +-------------+ |Needle1 | +-------------+ |Needle2 | +-------------+ |Needle3 | +-------------+ |Needle ... | +-------------+
 Volume = 1 SuperBlock + n Needle

SuperBlock

/* * Super block currently has 8 bytes allocated for each volume. * Byte 0: version, 1 or 2 * Byte 1: Replica Placement strategy, 000, 001, 002, 010, etc * Byte 2 and byte 3: Time to live. See TTL for definition * Rest bytes: Reserved */ type SuperBlock struct { version Version ReplicaPlacement *ReplicaPlacement Ttl *TTL }

SuperBlock 內維護的數據基本上就是該 Volume 的元數據。

  • ReplicaPlacement : 在後面的 Replication 會講
  • Ttl :Time To Live 爲了定時刪除的功能

【TTL】

定時刪除功能,這個感覺很酷炫,但是在Seaweedfs裏面的實現原理很簡單, 按 Volume 來進行分塊,當每次用戶上傳一個自帶TTL的文件(需要定時刪除的文件)時, 會把這個文件存儲在合適的 Volume 裏面(如何選出合適的 Volume 之後再說), 存儲的時候每個文件會帶有 TTL 這個屬性, 當讀取出來之後發現該文件已經過期(超時時間到),則會返回一個 Not Found 結果, 而每個 Volume 維護一個最大超時時間,當這個時間抵達時,說明整個 Volume 所有的文件都超時了, 然後 VolumeServer 通知 MasterServer 這個 Volume 已經被標識爲 Dead 狀態, 意味着 MasterServer 不會再爲這個 Volume 分配新的 Fid。 然後再經過一段合適的時間後由 VolumeServer 將這個 Volume 從磁盤上安全的刪除掉。 詳細請看在 Seaweedfs 自帶的文檔 ttl 

Needle

/* * A Needle means a uploaded and stored file. * Needle file size is limited to 4GB for now. */ type Needle struct { Cookie uint32 `comment:"random number to mitigate brute force lookups"` Id uint64 `comment:"needle id"` Size uint32 `comment:"sum of DataSize,Data,NameSize,Name,MimeSize,Mime"` Data []byte `comment:"The actual file data"` DataSize uint32 `comment:"Data size"` //version2 Flags byte `comment:"boolean flags"` //version2 NameSize uint8 //version2 Name []byte `comment:"maximum 256 characters"` //version2 MimeSize uint8 //version2 Mime []byte `comment:"maximum 256 characters"` //version2 LastModified uint64 //only store LastModifiedBytesLength bytes, which is 5 bytes to disk Ttl *TTL Checksum CRC `comment:"CRC32 to check integrity"` Padding []byte `comment:"Aligned to 8 bytes"` }

Needle 結構體裏面的 Cookie 和 Id 就是上文提過的 Fid 裏面的 Cookie 和 NeedleId, 其他就是一些存儲相關的變量,沒什麼奇淫巧計。就是簡單的存儲結構而已。

數據備份之 Replication

Replication 和 Topology 嚴重相關, 在配置文件中可以配置多種備份模式,詳見 seaweedfs-wiki 

+-----+---------------------------------------------------------------------------+ |001 |replicate once on the same rack | +-----+---------------------------------------------------------------------------+ |010 |replicate once on a different rack in the same data center | +-----+---------------------------------------------------------------------------+ |100 |replicate once on a different data center | +-----+---------------------------------------------------------------------------+ |200 |replicate twice on two other different data center | +-----+---------------------------------------------------------------------------+

比如在 001 模式,即在同一個 rack 中的不同 DataNode 中備份一份。 假設在 rack1 中含有 DataNode1, DataNode2, DataNode3 三個數據節點中【隨機】選出兩個數據節點, 比如選出 DataNode1, DataNode2 然後同時寫入這兩個數據節點。 假設 rack1 只有一個數據節點的時候,而備份模式是 001 模式, 則無法正常備份,服務會報錯。

注意到,選擇備份數據節點的方法是【隨機】,所以就會出現從三個數據節點中隨機選擇兩個的情況下,

curl -v -F "file=@/tmp/test.json" localhost:8081/5,1ce2111f1

topo.NextVolumeId 負責生成 VolumeId , 負責在 VolumeGrowth 裏的時候分配 Volume 的時候, 生成一個全局唯一的新 VolumeId, 在 Weed-fs 中,是支持 多 MasterServer 集羣的。 當有多個 MasterServer,生成一個全局唯一的新 VolumeId 是很重要, 在 Weed-fs 中是通過 goraft 來實現的。

【強一致性】

Seaweedfs 的備份實現是強一致性的。 當一個 VolumeServer 接受到上傳文件的 POST 請求時, 將該文件作爲一個 Needle 寫入本地 Volume 之後, 會根據該文件所分配的 VolumeId 判斷是否需要備份, 如果需要備份,則進行備份(需要請求另外其它的 VolumeServer 服務器)。 過程詳見 ReplicatedWrite (topology/store_replicate.go)。 當備份完畢後,再對該 POST 請求進行答覆。 所以用戶每次上傳圖片時,當收到了答覆之後, 則可以認爲此備份已完成。這個和最終一致性不同,屬於強一致性。

上述實現強一致性的過程中, 有個必要條件就是【 VolumeServer 需要知道往其它那些 VolumeServer 備份】。 在 Seaweedfs 的實現中是藉助 MasterServer 來實現, 因爲備份的基本單位是 Volume, 在 MasterServer 中,對每個 VolumeId 都維護對應的備份機器列表。 可以通過如下示例命令查看:

curl "localhost:9333/dir/lookup?volumeId=4&pretty=y" { "volumeId": "4", "locations": [ { "url": "127.0.0.1:8081", "publicUrl": "localhost:8081" }, { "url": "127.0.0.1:8080", "publicUrl": "localhost:8080" } ] }

如上示例中可以看出,對應的 volumeId=4 的 Volume, 可以看出對應的備份機器列表有兩臺,分別是 "127.0.0.1:8081" 和 "127.0.0.1:8080" 。

實際上對於每臺 VolumeServer 查找其它備份機器的時候, 也是通過如上 HTTP api 向 MasterServer 詢問。 只不過不是每次都詢問,因爲只要詢問過了之後就會緩存下來,只有在緩存裏面找不到才詢問。

【Collection】

示例如下:

啓動 MasterServer

weed master

啓動 VolumeServer

weed volume -dir="/tmp/data1" -max=5 -mserver="localhost:9333" -port=8080

申請Fid

curl "http://127.0.0.1:9333/dir/assign?collection=pictures" {"fid":"4,01d50c6fbf","url":"127.0.0.1:8080","publicUrl":"localhost:8080","count":1}
curl "http://127.0.0.1:9333/dir/assign?collection=mp3" {"error":"No free volumes left!"}
curl "http://127.0.0.1:9333/dir/assign?collection=pictures" {"fid":"5,0147ed0fb7","url":"127.0.0.1:8080","publicUrl":"localhost:8080","count":1}

申請Fid的示例解釋:

  1. 因爲默認情況下,VolumeServer 啓動時, 未申請任何 Volume,當第一次 /dir/assign 的時候, 會分配 Volume,因爲 weed volume 的參數 -max=5 所以一次性分配 5 個 Volume ,並且這 5 個 Volume 的 Collection 屬性都是 pictures, 甚至可以看到在 ls /tmp/data1 的結果如下:
/tmp/data1 pictures_1.dat pictures_1.idx pictures_2.dat pictures_2.idx pictures_3.dat pictures_3.idx pictures_4.dat pictures_4.idx pictures_5.dat pictures_5.idx

可以看出每個卷的文件名以 Collection 來命名。

2. 因爲已有的 5 個 Volume 的 Collection 屬性都是 pictures, 所以此時如果需要 /dir/assign 一個非 pictures Collection 的 Fid 時失敗,

3. 當申請一個屬於 pictures Collection 的 Fid 成功。

也就是在每次申請 Fid 時,會針對 Collection 進行檢查,來保證存入 Volume 的每個 Needle 所屬的 Collection 一致。 在實際應用中可以通過 Collection 來類別的分片。

【Volume 的大小限制】

在每次 VolumeServer 向 MasterServer 發送心跳信息的時候, 會在 storage.VolumeInfo.Size 裏面註明當前 Volume 的大小信息(Size)。 所以可以以此來限制 Volume 的大小。 如下函數:

func (vl *VolumeLayout) isWritable(v *storage.VolumeInfo) bool { return uint64(v.Size) < vl.volumeSizeLimit && v.Version == storage.CurrentVersion && !v.ReadOnly }

當 VolumeInfo.Size 大於 VolumeLayout.volumeSizeLimit 時, 則將該 Volume 標記爲不可寫。 而 VolumeLayout.volumeSizeLimit 的值可以在啓動 MasterServer 的時候配置。 由 weed help master 可知:

-volumeSizeLimitMB=30000: Master stops directing writes to oversized volumes.

每個 Volume 的最大 Size 默認是 30G , 而每個 VolumeServer 可以配置 n 個 Volume,根據所在機器不同的硬盤大小配置不同的 n . 由 weed help volume 可知:

-max="7": maximum numbers of volumes, count[,count]...

每個 VolumeServer 默認的 Volume 大小是 7 。

所以默認情況下,當一個 VolumeServer 使用的磁盤超過 7 * 30G = 210G 之後, 該 VolumeServer 屬於只讀狀態, MasterServer 不會再分配新的 Fid 給它。

但是其實這裏會有漏洞,如果此時不通過請求 MasterServer 獲取 Fid, 而是直接自己構造 Fid 向 VolumeServer POST 文件的話, VolumeServer 還是會一直接受上傳的文件, 直到大小超過在storage/needle.go 裏面寫死的一個常量:

MaxPossibleVolumeSize = 4 * 1024 * 1024 * 1024 * 8

其實在 VolumeServer 裏面也有維護一個變量叫 volumeSizeLimit ,

type Store struct { ... volumeSizeLimit uint64 //read from the master ... }

此變量的值是從 MasterServer 獲取的, 當每次 VolumeServer 寫入 Needle 到 Volume 的時候, 都會檢查 Volume Size 是否超過 volumeSizeLimit , 當超過的時候會打錯誤日誌, 但是不會停止寫入,也就是不會拒絕上傳的文件。 有且只有 當大小超過 MaxPossibleVolumeSize 的時候纔會拒絕寫入磁盤。

【擴容】

對於 Seaweedfs 來說,擴容非常簡單,

啓動 MasterServer:

./weed master -mdir="/tmp/weed_master_tmp"

啓動 VolumeServer1:

weed volume -dir="/tmp/data1" -max=5 -mserver="localhost:9333" -port=8080

當 VolumeServer1 因爲抵達 Volume 大小上限而無法繼續接受上傳數據時, 此時繼續 submit 上傳數據 MasterServer 則會返回錯誤(因爲在 MasterServer 內已經將 VolumeServer1 標記爲不可寫)。

curl -F "file=@/tmp/test.pdf" "127.0.0.1:9333/submit" {"error":"No free volumes left!"}

此時直接再啓動 VolumeServer2 即可

weed volume -dir="/tmp/data2" -max=5 -mserver="localhost:9333" -port=8081

此時 VolumeServer2 啓動之後會自動向 MasterServer 的 Topology 結構註冊新的 DataNode , 當 MasterServer 接受到新的 submit 請求的時候,會將該上傳文件寫入 VolumeServer2 (因爲此時 VolumeServer1 已經不可寫)。

也就是說如果當線上出現容量問題的時候,擴容只需要加機器即可,簡單有效。

總結

  • 每個 MasterServer 通過 Topology 維護多個 VolumeServer 。
  • 每個 VolumeServer 維護多個 Volume 。
  • 每個 Volume 包含多個 Needle ,Needle 即文件。
  • 多臺 VolumeServer 之間的多機備份實現是強一致性。
  • 多臺 MasterServer 之間的主從關係是是通過 goraft 實現。
  • 1.架構

    我們先了解一個概念:見附錄

    一個master:

    作爲cluster管理一個DataCenter名叫imgdatacenter1(抽象的概念);
    imgdatacenter1包含一個機櫃 rack名叫imgrack1(抽象的概念);
    imgrack1機櫃裏面有一個DataNode名叫datanode1(可以認爲DataNode是一個volume server );

     

    cd /home1/seaweeddir  //這是我的測試目錄,你這裏選擇你自己的目錄
    mkdir {mtmp,vtmp1,vtmp2,ftmp,mountdir}  //大括號內千萬別多空格,否則會出現問題
    weed master -ip=localhost -port=9333 -mdir=./mtmp (mtmp是你自定義的保存生成的序列文件id的文件夾)
    

    一個DataNode:(datanode1只是抽象的名字沒有實質的代碼賦值,下面通過地址來區分DataNode)

    就是上面的datanode1,定義裏面有10個volume,collection不先設置,DataCenter和rack都用下面的指令指定:

     

    weed volume  -dataCenter=imgdatacenter1 -rack=imgrack1  -ip=localhost -port=9991 -dir=./vtmp1 -max=10 -mserver=localhost:9333
    

    此時就在名爲imgdatacenter1的dataCenter中的名爲imgrack1的rack裏添加了一個地址爲localhost:9991的volume server。

    一個filer服務器

     

    weed scaffold -config=filer -output=.      //先生成filer.toml文件
    

    默認使用leveldb保存映射關係,打開filer.toml文件修改保存映射文件的文件夾爲ftmp(自定義)

     

    image.png

     

    然後啓動filer服務

     

    weed filer -ip=localhost -port=8888  -master=localhost:9333 
    

    本地映射filer

    mountdir 是本地任意目錄,filer.path後面跟你想映射的filer中的目錄,可以直接映射根目錄。

     

    sudo weed mount -filer=localhost:8888 -dir=/home1/seaweeddir/mountdir -filer.path=/  
    //sudo weed mount -filer=localhost:8888 -dir=~/folder_on_seaweedfs -filer.path=/home/chris -collection=chris
    

    關閉掛在需要關閉mount並且手動umont ~/mdir目錄,如果一般用戶失敗請使用root用戶

    2.驗證

    我們驗證下我們的服務啓動狀態,
    此時有一個DataCenters名爲imgdatacenter1,一個Racks名爲imgrack1,一個DataNodes地址是localhost:9991,且該DataNode的Volumes個數爲0,等我們新增文件的時候就會發現volumes個數纔會增加

     

    //這種返回表示master啓動成功且作爲了leader
    curl "http://localhost:9333/cluster/status?pretty=y"
    {
      "IsLeader": true,
      "Leader": "localhost:9333"
    }
    
    //此時有一個DataCenters名爲imgdatacenter1,一個Racks名爲imgrack1,一個DataNodes地址是localhost:9991,且該DataNode的Volumes個數爲0
    curl "http://localhost:9333/dir/status?pretty=y"
    {
      "Topology": {
        "DataCenters": [
          {
            "Free": 10,
            "Id": "imgdatacenter1",
            "Max": 10,
            "Racks": [
              {
                "DataNodes": [
                  {
                    "Free": 10,
                    "Max": 10,
                    "PublicUrl": "localhost:9991",
                    "Url": "localhost:9991",
                    "Volumes": 0
                  }
                ],
                "Free": 10,
                "Id": "imgrack1",
                "Max": 10
              }
            ]
          }
        ],
        "Free": 10,
        "Max": 10,
        "layouts": null
      },
      "Version": "1.10"
    }
    

    本地操作的方式往服務器新增一個文件

     

    cd /home1/image/mountdir
    cp /home1/image/1.jpg ./
    

    我們查看下系統狀態,(詳細數據參見附錄:上傳文件後的系統狀態)
    此時我們發現地址爲localhost:9991的datanode的Volumes數量變成了7個,說明當前新增了7個volume,因爲我們之前設置的volume最大個數時10,所有最多還能再新增3個volume。
    我們再看layouts,發現已經不是之前的null了,而是出現了一個名爲""的collection,有七個可以寫的volume。
    這是因爲如果我們沒有指定collection的時候,默認所有數據都保存在名爲""的collection中

    我們查看下文件上傳後volumeserver的狀態
    我們發現id爲4的volume的filecount爲1,說明該文件上傳到了這裏。

    我們你再看下filer的狀態
    多了個1.jpg文件

    我們再看下我們的掛載目錄

     

    ls /home1/seaweeddir/mountdir/
    1.jpg
    

    此時說明我們上傳文件就成功了

    此時我們可以操作本地文件系統中的目錄/home1/seaweeddir/mountdir,來操作我們的圖片服務器。
    然而批量操作本地文件系統的mount文件夾時不是併發的,需要經過fuse層,要想併發操作就需要直接操作filer服務。

    通過filer服務器做一些文件操作

    使用命令上傳

     

    curl -F [email protected] "http://localhost:8888/javascript/new_name.js"    # upload the file with a different name
    

    本地批量上傳文件

    使用weed filer.copy file_or_dir1 [file_or_dir2 file_or_dir3] http://localhost:8888/path/to/a/folder/ (多線程且繞過fuse層)
    我在本地/home1/image/staff 下有大量的圖片,這裏上傳到filer服務器的mystaff下,我們查看/home1/seaweeddir/mountdir/下,會發現多了個staff目錄,且目錄下也全部拷貝了圖片。

     

    weed filer.copy /home1/image/staff http://localhost:8888/mystaff
    

    刪除文件

     

    curl -X DELETE http://localhost:8888/path/to/file
    

    刪除文件夾

     

    curl -X DELETE http://localhost:8888/path/to/dir?recursive=true
    

    一些注意事項

    1.關閉volume mount時需要手動sudo mount -l /home1/seaweeddir/mountdir目錄,否則該目錄會導致終端卡死。
    2.刪除操作不會馬上清空磁盤,要想實時清空未使用的空間,請執行
    curl "http://localhost:9333/vol/vacuum"

    使用fid操作文件在filer的顯示

     

    curl http://localhost:9333/dir/assign
    {"fid":"7,03a0146c8ac8","url":"localhost:9991","publicUrl":"localhost:9991","count":1}
    
    curl -F file=@/home1/image/1.jpg http://localhost:9991/7,03a0146c8ac8 //在filer中找不到,因爲filer服務沒有保存映射關係,所有想使用filer,就得使用filer上傳文件,否則只能通過fid獲取信息。
    curl -F file=@/home1/image/1.jpg "http://localhost:8888/javascript/2.jpg"//在filer的javascript目錄下多了個2.jpg
    
    weed download -server="localhost:9333" -dir="D:\data3" 4,012d48fa67 //可以通過fid下載文件
    

    結尾

    到這裏一個圖片服務器就搭建起來了,
    真正要熟悉使用seaweedfs需要仔細閱讀官方wiki,並且查看源碼和實現依賴的論文來了解實現原理。
    剩餘的像數據備份,服務器雲備份等請看官網wiki:
    https://github.com/chrislusf/seaweedfs/wiki/Failover-Master-Server
    https://github.com/chrislusf/seaweedfs/wiki/Amazon-S3-API
    https://github.com/chrislusf/seaweedfs/wiki/Async-Replication-to-another-Filer

    總結

     

    cd /home1/seaweeddir 
    mkdir {mtmp,vtmp1,vtmp2,ftmp,mountdir} 
    weed scaffold -config=filer -output=. 
    vim filer.toml (修改leveldb的dir爲"./ftmp")
    weed master -ip=localhost -port=9333 -mdir=./mtmp
    weed volume  -dataCenter=imgdatacenter1 -rack=imgrack1  -ip=localhost -port=9991 -dir=./vtmp1 -max=10 -mserver=localhost:9333
    weed filer -ip=localhost -port=8888  -master=localhost:9333 -collection=test
    sudo weed mount -filer=localhost:8888 -dir=/home1/seaweeddir/mountdir -filer.path=/   -collection=test
    //關閉服務後執行 sudo umount -l /home1/seaweeddir/mountdir 取消掛載
    //此時就可以使用filer通過web操作文件了,而且也可以通過/home1/seaweeddir/mountdir本地操作文件了。
    //或者這麼理解,sudo weed mount只能用sudo umount -l 取消掛載,而不是直接kill進程。
    

    附錄:

    其他上傳下載的命令

     

    weed upload -master=localhost:9333 file1 [file2 file3]
    weed upload -master=localhost:9333 -dir=one_directory -include=*.pdf
    

     

    //指定幾個fid下載到本地one_directory中
    weed download -server=localhost:9333 -dir=one_directory fid1 [fid2 fid3 ...]
    

     

    //導出id爲7的volume到/dir/name.tar,/tmp是volume保存的地址,只導出比2006-01-02T15:04:05新的文件
    weed export -dir=/tmp -volumeId=7 -o=/home1/seaweeddir/exp2/name.tar -fileNameFormat={{.Name}} -newer='2006-01-02T15:04:05'
    

    一些概念

    1.topology 是樹狀結構,DataNode 是樹的葉子節點, DataCenter 和 Rack 是樹的非葉子節點, DataCenter 是 Rack 的父母節點。
    2.在 MasterServer 維護的拓撲結構裏, 是把 VolumeServer 的相關信息存儲在 DataNode 裏,每次查找對應的DataNode,都需要從 DataCenter -> Rack -> DataNode 依次找下去。
    3."fid":"1,01f96b93eb" 就是 Fid,Fid 由三個部分組成 【VolumeId, NeedleId, Cookie】 組成

     

        VolumeId: 1 32bit 存儲的物理卷的Id 
        NeedleId: 01 64bit 全局唯一NeedleId,每個存儲的文件都不一樣(除了互爲備份的)。
        Cookie: f96b93eb 32bit Cookie值,爲了安全起見,防止惡意攻擊
    

    4.VolumeId 是由 MasterServer 分配給 VolumeServer, 每個 VolumeServer 都維護個 n 個 Volume , 每個Volume 都有一個專屬 VolumeId,之後會細說。 Needle 屬於 Volume 裏面的一個單元
    5.dir 就是該 Volume 所在的目錄,
    6.Collection 很有用,每個 Volume 只能對應同一個 Collection,不同 Collection 的圖片存儲在不同 Volume,所以同一個 Volume 只能針對某一個 Collection ,而 同一個 Collection 的圖片可能分佈在不同的 Volume
    7.Replication 和 Topology 嚴重相關,比如在 001 模式,即在同一個 rack 中的不同 DataNode 中備份一份。假設在 rack1 中含有 DataNode1, DataNode2, DataNode3 三個數據節點中【隨機】選出兩個數據節點, 比如選出 DataNode1, DataNode2 然後同時寫入這兩個數據節點。 假設 rack1 只有一個數據節點的時候,而備份模式是 001 模式, 則無法正常備份,服務會報錯。
    8.VolumeServer 啓動時, 未申請任何 Volume,當第一次 /dir/assign 的時候, 會分配 Volume
    9.每個 VolumeServer 默認的 Volume 大小是 7 。默認情況下,當一個 VolumeServer 使用的磁盤超過 7 *30G = 210G 之後, 該 VolumeServer 屬於只讀狀態, MasterServer 不會再分配新的 Fid 給它。
    10.每個 MasterServer 通過 Topology 維護多個 VolumeServer 。
    11.每個 VolumeServer 維護多個 Volume 。
    12.每個 Volume 包含多個 Needle ,Needle 即文件。
    13.多臺 VolumeServer 之間的多機備份實現是強一致性。
    14.多臺 MasterServer 之間的主從關係是是通過 goraft 實現。

    collection的說明

    如果我們沒有指定collection的時候,默認所有數據都保存在名爲""的collection中,
    0.按照collection刪除

     

    Delete Collection
    curl "http://localhost:9333/col/delete?collection=xxx&pretty=y"
    

    1.預申請volume的時候指定collection

     

    //預申請4個屬於名爲turbo的collection 的volume
    curl "http://localhost:9333/vol/grow?collection=turbo&count=4"
    

    2.添加filer時指定collection

     

    //此時所有通過filer新增的數據都在名爲myfiler的collection中
    weed filer -ip=localhost -port=8888  -master=localhost:9333  -collection=myfiler
    
  • mount時指定collection
  •  

    //只掛在指定collection
    weed mount -filer=localhost:8888 -dir=~/folder_on_seaweedfs -filer.path=/home/chris -collection=chris
    

    4.其他

     

    curl "http://127.0.0.1:9333/dir/assign?collection=pictures"
    curl -F @file=./hello1.txt http://10.0.40.58:9333/submit?collection=test_crash
    weed upload -collection myfiles -master=localhost:9333 XXX.txt
    

    上傳文件後的系統狀態

     

    curl "http://localhost:9333/dir/status?pretty=y"
    {
      "Topology": {
        "DataCenters": [
          {
            "Free": 3,
            "Id": "imgdatacenter1",
            "Max": 10,
            "Racks": [
              {
                "DataNodes": [
                  {
                    "Free": 3,
                    "Max": 10,
                    "PublicUrl": "localhost:9991",
                    "Url": "localhost:9991",
                    "Volumes": 7
                  }
                ],
                "Free": 3,
                "Id": "imgrack1",
                "Max": 10
              }
            ]
          }
        ],
        "Free": 3,
        "Max": 10,
        "layouts": [
          {
            "collection": "",
            "replication": "000",
            "ttl": "",
            "writables": [
              1,
              2,
              3,
              4,
              5,
              6,
              7
            ]
          }
        ]
      },
      "Version": "1.10"
    }
    

    我們查看下文件上傳後volumeserver的狀態
    我們發現id爲4的volume的filecount爲1,說明該文件上傳到了這裏。

     

    curl "http://localhost:9991/status?pretty=y"
    {
      "Version": "1.10",
      "Volumes": [
        {
          "Id": 1,
          "Size": 0,
          "ReplicaPlacement": {
            "SameRackCount": 0,
            "DiffRackCount": 0,
            "DiffDataCenterCount": 0
          },
          "Ttl": {},
          "Collection": "",
          "Version": 3,
          "FileCount": 0,
          "DeleteCount": 0,
          "DeletedByteCount": 0,
          "ReadOnly": false
        },
        {
          "Id": 2,
          "Size": 0,
          "ReplicaPlacement": {
            "SameRackCount": 0,
            "DiffRackCount": 0,
            "DiffDataCenterCount": 0
          },
          "Ttl": {},
          "Collection": "",
          "Version": 3,
          "FileCount": 0,
          "DeleteCount": 0,
          "DeletedByteCount": 0,
          "ReadOnly": false
        },
        {
          "Id": 3,
          "Size": 0,
          "ReplicaPlacement": {
            "SameRackCount": 0,
            "DiffRackCount": 0,
            "DiffDataCenterCount": 0
          },
          "Ttl": {},
          "Collection": "",
          "Version": 3,
          "FileCount": 0,
          "DeleteCount": 0,
          "DeletedByteCount": 0,
          "ReadOnly": false
        },
        {
          "Id": 4,
          "Size": 77285,
          "ReplicaPlacement": {
            "SameRackCount": 0,
            "DiffRackCount": 0,
            "DiffDataCenterCount": 0
          },
          "Ttl": {},
          "Collection": "",
          "Version": 3,
          "FileCount": 1,
          "DeleteCount": 0,
          "DeletedByteCount": 0,
          "ReadOnly": false
        },
        {
          "Id": 5,
          "Size": 0,
          "ReplicaPlacement": {
            "SameRackCount": 0,
            "DiffRackCount": 0,
            "DiffDataCenterCount": 0
          },
          "Ttl": {},
          "Collection": "",
          "Version": 3,
          "FileCount": 0,
          "DeleteCount": 0,
          "DeletedByteCount": 0,
          "ReadOnly": false
        },
        {
          "Id": 6,
          "Size": 0,
          "ReplicaPlacement": {
            "SameRackCount": 0,
            "DiffRackCount": 0,
            "DiffDataCenterCount": 0
          },
          "Ttl": {},
          "Collection": "",
          "Version": 3,
          "FileCount": 0,
          "DeleteCount": 0,
          "DeletedByteCount": 0,
          "ReadOnly": false
        },
        {
          "Id": 7,
          "Size": 0,
          "ReplicaPlacement": {
            "SameRackCount": 0,
            "DiffRackCount": 0,
            "DiffDataCenterCount": 0
          },
          "Ttl": {},
          "Collection": "",
          "Version": 3,
          "FileCount": 0,
          "DeleteCount": 0,
          "DeletedByteCount": 0,
          "ReadOnly": false
        }
      ]
    }
    

    我們你再看下filer的狀態
    多了個1.jpg文件

     

    curl  -H "Accept: application/json" "http://localhost:8888/?pretty=y" 
    {
      "Path": "",
      "Entries": [
        {
          "FullPath": "/1.jpg",
          "Mtime": "2018-12-18T10:38:18+08:00",
          "Crtime": "2018-12-18T10:38:18+08:00",
          "Mode": 436,
          "Uid": 1000,
          "Gid": 1000,
          "Mime": "image/jpeg",
          "Replication": "",
          "Collection": "",
          "TtlSec": 0,
          "chunks": [
            {
              "file_id": "4,0189b08312",
              "size": 77244,
              "mtime": 1545100698715493243,
              "e_tag": "32f4abc5"
            }
          ]
        }
      ],
      "Limit": 100,
      "LastFileName": "1.jpg",
      "ShouldDisplayLoadMore": false
    }
    

    我們再看下我們的掛載目錄

     

    ls /home1/seaweeddir/mountdir/
    1.jpg


     

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章