POSIX是否真的不適合對象存儲?基於數據的答案

本篇文章作者對MinIO文章中的觀點提出質疑,該文章認為POSIX不適合用於物件儲存。他進行了全面的測試,涉及MinIO的s3fs-fuse與JuiceFS。結果顯示,MinIO與JuiceFS表現出色,而s3fs-fuse則有所滯後。在小檔案覆寫情境下,JuiceFS FUSE-POSIX的表現超越了其他解決方案

最近,我在MinIO博客上讀到一篇名為”在物件儲存上建立檔案系統是個壞主意。以下是原因“的文章。作者以s3fs-fuse為例,說明使用可攜式作業系統介面(POSIX)方法存取MinIO資料時遇到的效能挑戰,強調其效能遠落後於直接存取MinIO。作者將這些效能問題歸咎於POSIX固有的缺陷。然而,我們的經驗與此結論有所不同。

POSIX是一套實用且廣泛採用的標準。遵循POSIX開發的軟件能夠確保在不同操作系統間的兼容性和可移植性。各行各業中的大多數應用程序都遵循POSIX標準。隨著雲計算、大數據和AI技術的進步,以及存儲數據量的日益增加,對於像對象存儲這樣的彈性存儲解決方案的需求也在增長。儘管像MinIO這樣的對象存儲提供了多種語言的SDK,但許多傳統應用程序在將其代碼適配到使用對象存儲API時仍面臨困難。這導致了各種存儲產品在對象存儲之上實現POSIX接口以滿足這種不靈活的需求。

業界中有許多產品,如Ceph、JuiceFS和Weka,已成功在對象存儲上實現了POSIX接口。這些解決方案擁有龐大的用戶群和眾多成功案例,並在性能方面表現出色。

雖然POSIX確實具有相當的複雜性,但相關問題並非無法克服。出於對這些說法的尊重和驗證的願望,我搭建了一個測試環境,採用了與MinIO文章中相同的樣本數據和測試方法,進行了驗證。

產品比較與測試目標

為了提供全面的評估,我將JuiceFS引入比較中。

JuiceFS 是一個開源的雲原生分散式檔案系統,採用物件儲存作為資料儲存層,並依賴一個獨立的資料庫來儲存元資料。它提供了多種存取方式,包括 POSIX API、S3 API、CSI Driver、HDFS API 及 WebDAV,並具備獨特的資料區塊化、快取及並行讀寫機制。JuiceFS 是一個檔案系統,本質上與工具如s3fs-fuse不同,後者僅將物件儲存轉換為 POSIX 協議。

引入 JuiceFS 進行比較,旨在客觀評估在物件儲存之上實現 POSIX 等協議的優缺點。

I conducted the following two tests on MinIO, JuiceFS, and s3fs-fuse:

  • 撰寫一個 10 GB 的檔案
  • 使用 Pandas 覆蓋小檔案

三種解決方案均使用了部署在獨立伺服器上的 MinIO 實例作為底層儲存。測試樣本使用了一個 10 GB 的檔案,即 MinIO 文章中提到的相同CSV 檔案

本文中的所有環境、軟體、腳本及樣本資料均附有完整的程式碼和指導,確保您能夠重現環境及測試結果。

伺服器及測試環境設定

兩台配置相同的雲端伺服器:

  • 系統:Ubuntu 22.04 x64
  • CPU:8 核心
  • RAM:16 GB
  • SSD:500 GB
  • 網路:VPC

每台伺服器的資訊:

Server IP Purpose
Server A 172.16.254.18 Deploying the MinIO instance
Server B 172.16.254.19 As the test environment

伺服器 A 準備工作

1. 我使用Docker在Server A上部署了MinIO,执行了以下命令:

# 创建一个专用目录并导航至该目录。
mkdir minio && cd minio

# 创建配置文件。
mkdir config
touch config/minio

2. 我将以下信息写入到config/minio文件中:

MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=abc123abc
MINIO_VOLUMES="/mnt/data"

3. 我创建了MinIO容器:

sudo docker run -d --name minio \
  -p 9000:9000 \
  -p 9090:9090 \
  -v /mnt/minio-data:/mnt/data \
  -v ./config/minio:/etc/config.env \
  -e "MINIO_CONFIG_ENV_FILE=/etc/config.env" \
  --restart unless-stopped \
  minio/minio server --console-address ":9090"

4. 在MinIO的Web控制台中,我预先创建了三个存储桶:

Bucket name Purpose
test-minio For testing MinIO
test-juicefs For testing JuiceFS
test-s3fs For testing s3fs-fuse

Server B准备工作

1. 我下载了10GB的测试样本文件。

curl -LO https://data.cityofnewyork.us/api/views/t29m-gskq/rows.csv?accessType=DOWNLOAD

2. 我安装了mc客户端。

mc是由MinIO项目开发的命令行文件管理器,它允许在Linux命令行中对本地和S3兼容的对象存储进行读写操作。mc cp命令在数据复制过程中提供实时进度和速度更新,便于观察各种测试。

注意:为了保持测试的公平性,所有三种方法都使用mc进行文件写入测试。

# 下载mc。
wget https://dl.min.io/client/mc/release/linux-amd64/mc

# 检查mc版本。
mc -v
mc version RELEASE.2023-09-20T15-22-31Z (commit-id=38b8665e9e8649f98e6162bdb5163172e6ecc187)
Runtime: go1.21.1 linux/amd64

# 安装mc。
sudo install mc /usr/bin

# 为MinIO设置别名。
mc alias set my http://172.16.254.18:9000 admin abc123abc

3. 我下载了s3fs-fuse

sudo apt install s3fs

# 检查版本。
s3fs --version
Amazon Simple Storage Service File System V1.93 (commit:unknown) with OpenSSL

# 设置对象存储访问密钥。
echo admin:abc123abc >  ~/.passwd-s3fs

# 修改密钥文件权限。
chmod 600  ~/.passwd-s3fs

# 创建挂载目录。
mkdir mnt-s3fs

# 挂载对象存储。
s3fs test-s3fs:/ /root/mnt-s3fs -o url=http://172.16.254.18:9000 -o use_path_request_style

4. 我安装了JuiceFS。

I used the official script to install the latest JuiceFS Community Edition.

# 一键安装脚本
curl -sSL https://d.juicefs.com/install | sh -

# 检查版本。
juicefs version
juicefs version 1.1.0+2023-09-04.08c4ae6

5. 我建立了一個文件系統。JuiceFS 是一種使用前需先建立的文件系統。除了對象存儲外,它還需要一個數據庫作為元數據引擎。它支援多種數據庫。在此,我使用了常用的Redis作為元數據引擎。

注意:我已在Server A上安裝了Redis,可通過172.16.254.18:6379無密碼訪問。安裝過程在此省略,詳情可參考Redis文檔。

# 建立文件系統。
juicefs format --storage minio \
--bucket http://172.16.254.18:9000/test-juicefs \
--access-key admin \
--secret-key abc123abc \
--trash-days 0 \
redis://172.16.254.18/1 \
myjfs

6. 我通過更常用的POSIX和S3 API方法訪問了JuiceFS,並測試了它們的性能。

# 創建掛載目錄。
mkdir ~/mnt-juicefs

# 以POSIX模式掛載文件系統。
juicefs mount redis://172.16.254.18/1 /root/mnt-juicefs

# 使用S3 API方法訪問文件系統。
export MINIO_ROOT_USER=admin
export MINIO_ROOT_PASSWORD=abc123abc
juicefs gateway redis://172.16.254.18/1 0.0.0.0:9000

# 在mc中為JuiceFS S3 API設置別名。
mc alias set juicefs http://172.16.254.18:9000 admin abc123abc

注意:JuiceFS Gateway也可部署在Server A或任何其他可通過互聯網訪問的服務器上,因為它提供了基於網絡的S3 API。

測試與結果

以下是我測試的快速總結與結果:

Test MinIO S3FS-FUSE JuiceFS
(FUSE)
JuiceFS
(S3 gateway)
Writing a 10 GB file 0m27.651s 3m6.380s 0m28.107s 0m28.091s
Overwriting small files with Pandas 0.83s 0.78s 0.46s 0.96s

測試1:寫入一個10GB文件

此測試旨在評估寫入大型文件的性能。所需時間越短,性能越好。我使用time命令來測量寫操作的持續時間,提供了三個指標:

  • real: 指令從開始到結束的實際時間,包含所有等待時間,如等待I/O操作完成、等待進程切換及資源等待。
  • user: 在用戶模式下執行的時間,表示用於執行用戶代碼的CPU時間,通常代表指令的計算工作負載。
  • sys: 在核心模式下執行的時間,表示用於執行核心代碼的CPU時間,通常代表與系統調用相關的工作負載,如文件I/O和進程管理。

MinIO

I ran the following command to perform a copy test:

time mc cp ./2018_Yellow_Taxi_Trip_Data.csv  my/test-minio/

直接向MinIO寫入10GB文件的結果:

real    0m27.651s
user    0m10.767s
sys 0m5.439s

s3fs-fuse

I ran the following command to perform a copy test:

time mc cp ./2018_Yellow_Taxi_Trip_Data.csv /root/mnt-s3fs/

直接向s3fs-fuse寫入10GB文件的結果:

real 3m6.380s
user 0m0.012s
sys 0m5.459s

注意:儘管s3fs-fuse的寫入時間為3分06秒,但並未出現MinIO文章中所描述的寫入失敗情況。

JuiceFS

I tested the performance of JuiceFS for large file writes using both the POSIX and S3 API methods:

# POSIX寫入測試
time mc cp ./2018_Yellow_Taxi_Trip_Data.csv /root/mnt-juicefs/

# S3 API寫入測試
time mc cp ./2018_Yellow_Taxi_Trip_Data.csv  juicefs/myjfs/

JuiceFS POSIX寫入10GB文件的結果:

real    0m28.107s
user    0m0.292s
sys 0m6.930s

JuiceFS S3 API寫入10GB文件的結果:

real    0m28.091s
user    0m13.643s
sys 0m4.142s

大文件寫入結果總結

下圖顯示了測試結果:

Large file write results (lower is better)

測試結果顯示,無論是直接向MinIO還是JuiceFS寫入,兩者性能相當,均在約30秒內完成任務。相比之下,s3fs-fuse寫入10GB文件耗時超過3分鐘,約為前兩者的六倍慢

在處理大型檔案時,mc利用Multipart API將檔案分塊上傳至S3介面。相反地,s3fs-fuse僅能以單執行緒方式寫入POSIX。JuiceFS則會自動將大型檔案分割成塊,並在連續寫入時並行寫入MinIO,確保性能與直接寫入MinIO相當。而S3FS則是先以單執行緒方式寫入快取磁碟,然後再將檔案分塊上傳至MinIO,導致寫入時間較長。

根據計算,寫入一個10GB的檔案耗時30秒,平均速度為333MB/s。這受到雲端伺服器SSD頻寬的限制。這些測試結果表明,無論是MinIO還是JuiceFS都能充分利用本地SSD頻寬,且隨著伺服器雲端硬碟和網路頻寬的提升,其性能也將提升。

測試2:使用Pandas覆蓋小檔案

本測試評估了物件儲存系統在小檔案覆蓋情境下的性能。每個軟體的測試腳本略有不同。您可以在此處找到所有腳本代碼

MinIO

I got the test script and ran the test:

# 獲取測試腳本。
curl -LO https://gist.githubusercontent.com/yuhr123/7acb7e6bb42fb0ff12f3ba64d2cdd7da/raw/30c748e20b56dec642a58f9cccd7ea6e213dab3c/pandas-minio.py

# 運行測試。
python3 pandas-minio.py

結果如下:

Execution time: 0.83 seconds

s3fs-fuse

I got the test script and ran the test:

# 獲取測試腳本。
curl -LO gist.githubusercontent.com/yuhr123/7acb7e6bb42fb0ff12f3ba64d2cdd7da/raw/30c748e20b56dec642a58f9cccd7ea6e213dab3c/pandas-s3fs.py

# 運行測試。
python3 pandas-s3fs.py

測試結果如下:

Execution time: 0.78 seconds

JuiceFS POSIX

I got the test script and ran the test:

# 獲取測試腳本。
curl -LO gist.githubusercontent.com/yuhr123/7acb7e6bb42fb0ff12f3ba64d2cdd7da/raw/30c748e20b56dec642a58f9cccd7ea6e213dab3c/pandas-juicefs-posix.py

# 運行測試。
python3 pandas-juicefs-posix.py

測試結果如下:

Execution time: 0.43 seconds

JuiceFS S3 API

I got the test script and ran the test:

# 獲取測試腳本。
curl -LO https://gist.githubusercontent.com/yuhr123/7acb7e6bb42fb0ff12f3ba64d2cdd7da/raw/30c748e20b56dec642a58f9cccd7ea6e213dab3c/pandas-juicefs-s3api.py

# 運行測試。
python3 pandas-juicefs-s3api.py

測試結果如下:

Execution time: 0.86 seconds

Pandas小文件覆寫總結

下圖顯示了測試結果:

Pandas overwrite results (lower is better)

在此測試中,JuiceFS FUSE-POSIX展現了最快的速度,幾乎是其他解決方案的兩倍。MinIO、s3fs-fuse和JuiceFS S3 Gateway表現相近。從小文件覆寫的角度來看,POSIX接口證明更為高效,性能優於對象存儲接口。

問題與分析

問題1:為何S3FS如此緩慢?

分析:從測試數據來看,當寫入相同的10GB文件時,S3FS耗時3分鐘,而MinIO和JuiceFS均在約30秒內完成任務。這一顯著的性能差異主要源於不同的技術實現。當s3fs-fuse寫入文件時,它首先將文件寫入本地臨時文件,然後以塊的形式上傳到對象存儲。如果本地磁盤空間不足,它會同步上傳。這需要在本機磁盤和S3存儲之間複製數據。因此,大文件或大量文件會導致性能下降。

此外,S3FS依賴於底層對象存儲的元數據管理能力。當處理大量文件時,頻繁與對象存儲交互以檢索元數據對性能影響顯著。簡而言之,寫入S3FS的文件大小和總量越大,相應的性能開銷也越大。

問題二:為何JuiceFS更快?

分析:在測試中,JuiceFS和S3FS均通過FUSE進行讀寫操作。JuiceFS充分利用了磁盤帶寬,類似於MinIO,但未遭遇S3FS那樣的性能問題。

答案在於它們各自的技術架構。在文件寫入過程中,數據經由FUSE層處理時,JuiceFS採用高並發、緩存和數據分塊技術,以減少FUSE層與底層對象存儲之間的通信開銷。這使得JuiceFS能同時處理更多文件的讀寫請求,降低等待時間和傳輸延遲。

另外,JuiceFS使用專用數據庫(在此例中為Redis)管理元數據。面對大量文件時,獨立的元數據引擎能有效減輕負載,加快文件定位速度。

結論

上述測試表明,以物件儲存為基礎並在其上實現POSIX介面,並不一定會導致性能損失。無論是寫入大型還是小型檔案,JuiceFS展現出的性能與直接使用MinIO寫入相當,且不會因POSIX存取而降低底層物件儲存的性能。此外,在Pandas表格覆寫方面,JuiceFS FUSE-POSIX的性能保持一致,甚至將近是MinIO的兩倍。

測試結果顯示,某些軟體如s3fs-fuse在S3 API與POSIX介面之間轉換時可能會遇到性能下降。雖然它對於暫時性的S3存取是一個便利的工具,但對於穩定且高性能的長期使用,需要仔細研究和驗證以選擇更合適的解決方案。

對於簡單的非結構化檔案歸檔,直接使用MinIO或雲端物件儲存是一個好選擇。然而,在涉及大規模資料儲存與處理的場景,如AI模型訓練、大數據分析、Kubernetes資料持久化及其他頻繁的讀寫操作,JuiceFS獨立的元資料管理、並發讀寫能力及快取機制提供了卓越的性能。它是一個值得考慮的高性能檔案系統解決方案。

Source:
https://dzone.com/articles/is-posix-really-unsuitable-for-object-stores-a-dat