高效儲存數億個小文件。 自託管解決方案

高效儲存數億個小文件。 自託管解決方案

親愛的社區,本文將重點放在如何有效地儲存和檢索數億個小文件。 現階段,最終的解決方案是針對 POSIX 相容的檔案系統提出的,完全支援鎖,包括叢集鎖,而且看起來甚至不需要拐杖。

所以我為此目的編寫了自己的自訂伺服器。
在實現這個任務的過程中,我們成功地解決了主要問題,同時節省了磁碟空間和RAM,而我們的叢集檔案系統無情地消耗了磁碟空間和RAM。 實際上,如此多的文件對於任何叢集檔案系統都是有害的。

這個想法是這樣的:

簡單來說,小檔案透過伺服器上傳,直接儲存到檔案中,也可以從中讀取,大檔案並排放置。 方案:1個資料夾=1個檔案,總共有幾百萬個小文件檔案,而不是幾億個文件。 所有這一切都是完全實現的,無需任何腳本或將檔案放入 tar/zip 檔案中。

我會盡量簡短,如果貼文很長,我提前道歉。

這一切都始於這樣一個事實:我在世界上找不到合適的伺服器,可以將透過 HTTP 協定接收的資料直接保存到檔案中,而沒有傳統檔案和物件儲存固有的缺點。 而搜尋的原因是由10台伺服器組成的Origin叢集已經發展到了相當大的規模,其中已經累積了250,000,000億個小文件,而且成長的趨勢還沒有停止。

對於那些不喜歡閱讀文章的人來說,有些文件會更容易:

這裡 и 這裡.

同時還有 docker,現在有一個選項只包含 nginx,以防萬一:

docker run -d --restart=always -e host=localhost -e root=/var/storage 
-v /var/storage:/var/storage --name wzd -p 80:80 eltaline/wzd

下一篇:

如果有很多文件,則需要大量資源,最糟糕的是其中一些資源被浪費了。 例如,當使用叢集檔案系統(在本例中為 MooseFS)時,無論檔案的實際大小為何,它始終至少佔用 64 KB。 也就是說,對於大小為 3、10 或 30 KB 的文件,磁碟上需要 64 KB。 如果有 2 億個文件,我們就會遺失 10 到 1 TB。 不可能無限期地建立新文件,因為 MooseFS 有一個限制:每個文件的一個副本不能超過 XNUMX 億個文件。

隨著檔案數量的增加,元資料需要大量 RAM。 頻繁的大型元資料轉儲也會導致 SSD 驅動器的磨損。

wZD 伺服器。 我們把東西按順序放在磁碟上。

伺服器是用 Go 寫的。 首先,我需要減少文件數量。 怎麼做? 由於存檔,但在這種情況下沒有壓縮,因為我的檔案只是壓縮圖片。 BoltDB 來救援,但它的缺點仍然需要消除,這在文件中得到了反映。

總的來說,在我的例子中,Bolt 檔案只剩下 10 萬個,而不是 1 億個。 如果我有機會改變目前的目錄檔案結構,就有可能將其減少到大約 XNUMX 萬個檔案。

所有小檔案都打包到 Bolt 檔案中,Bolt 檔案會自動接收它們所在目錄的名稱,所有大型檔案都保留在檔案旁邊;打包它們沒有意義,這是可自訂的。 小的被存檔,大的保持不變。 伺服器與兩者透明地工作。

wZD 伺服器的架構和功能。

高效儲存數億個小文件。 自託管解決方案

該伺服器在 Linux、BSD、Solaris 和 OSX 作業系統下運作。 我只在 Linux 下測試了 AMD64 架構,但它應該適用於 ARM64、PPC64、MIPS64。

主要特點:

  • 多線程;
  • 多伺服器,提供容錯和負載平衡;
  • 為使用者或開發者提供最大的透明度;
  • 支援的 HTTP 方法:GET、HEAD、PUT 和 DELETE;
  • 透過客戶端標頭控制讀寫行為;
  • 支援靈活的虛擬主機;
  • 讀寫時支援CRC資料完整性;
  • 半動態緩衝區可實現最小記憶體消耗和最佳網路效能調整;
  • 延遲資料壓縮;
  • 此外,還提供多執行緒歸檔程式 wZA,用於在不停止服務的情況下遷移檔案。

真實體驗:

我已經在即時資料上開發和測試伺服器和歸檔器很長時間了,現在它可以在一個叢集上成功運行,該叢集包含位於單獨 SATA 磁碟機上 250,000,000 個目錄中的 15,000,000 個小檔案(圖片)。 由 10 台伺服器組成的叢集是安裝在 CDN 網路後面的來源伺服器。 為了提供服務,使用了 2 個 Nginx 伺服器 + 2 個 wZD 伺服器。

對於決定使用此伺服器的人來說,明智的做法是在使用之前規劃好目錄結構(如果適用)。 讓我立即做出保留,伺服器並不打算將所有內容都塞進 1 Bolt 檔案中。

性能測試:

壓縮檔案的大小越小,對其執行 GET 和 PUT 操作的速度就越快。 讓我們比較一下 HTTP 客戶端寫入常規檔案和 Bolt 檔案以及讀取的總時間。 對大小為 32 KB、256 KB、1024 KB、4096 KB 和 32768 KB 的檔案進行了比較。

使用 Bolt 檔案時,會檢查每個檔案的資料完整性(使用 CRC),在記錄之前和記錄之後,會發生即時讀取和重新計算,這自然會帶來延遲,但最主要的是資料安全。

我在 SSD 驅動器上進行了性能測試,因為在 SATA 驅動器上的測試沒有顯示出明顯的差異。

根據測試結果繪製圖表:

高效儲存數億個小文件。 自託管解決方案
高效儲存數億個小文件。 自託管解決方案

正如您所看到的,對於小文件,歸檔文件和非歸檔文件之間的讀寫時間差異很小。

當測試讀取和寫入 32 MB 大小的檔案時,我們得到了完全不同的情況:

高效儲存數億個小文件。 自託管解決方案

讀取檔案的時間差在5-25ms以內。 如果進行錄音,情況會更糟,差異約為 150 毫秒。 但在這種情況下,不需要上傳大文件;這樣做根本沒有意義;它們可以與檔案分開保存。

*從技術上講,您可以使用此伺服器來執行需要 NoSQL 的任務。

使用wZD伺服器的基本方法:

載入常規文件:

curl -X PUT --data-binary @test.jpg http://localhost/test/test.jpg

將檔案上傳到 Bolt 檔案(如果未超過伺服器參數 fmaxsize,此參數決定存檔中可以包含的最大檔案大小;如果超過,則檔案會照常上傳到檔案旁邊):

curl -X PUT -H "Archive: 1" --data-binary @test.jpg http://localhost/test/test.jpg

下載文件(如果磁碟上和存檔中存在同名文件,則下載時預設優先下載未存檔的文件):

curl -o test.jpg http://localhost/test/test.jpg

從 Bolt 檔案下載檔案(強制):

curl -o test.jpg -H "FromArchive: 1" http://localhost/test/test.jpg

其他方法的描述在文檔中。

wZD 文件
wZA 文檔

伺服器目前僅支援 HTTP 協定;尚不支援 HTTPS。 也不支援POST方法(尚未決定是否需要)。

誰深入原始碼就會發現那裡有奶油糖,不是每個人都喜歡它,但我沒有將主要程式碼與Web框架的功能綁定在一起,除了中斷處理程序,所以將來我可以快速重寫它以適應幾乎任何引擎。

TODO:

  • 開發您自己的複製器和分發器 + geo,以便在沒有叢集檔案系統的大型系統中使用的可能性(成人的一切)
  • 如果元資料完全遺失,則可以完全反向恢復元資料(如果使用分發器)
  • 本機協定能夠使用持久性網路連接和不同程式語言的驅動程式
  • 使用 NoSQL 元件的高階可能性
  • 對 Bolt 檔案內的文件或值以及常規文件進行不同類型的壓縮(gzip、zstd、snappy)
  • 對 Bolt 檔案內的文件或值以及常規文件進行不同類型的加密
  • 伺服器端視訊轉換延遲,包括 GPU 上的視訊轉換

我擁有一切,我希望這個伺服器對某人有用,BSD-3許可證,雙重版權,因為如果沒有我工作的公司,伺服器就不會被編寫。 我是唯一的開發者。 對於您發現的任何錯誤和功能請求,我將不勝感激。

來源: www.habr.com

添加評論