基於檔案語義實現S3介面語義的注意事項

jackieathome發表於2024-04-06

本文標題中提到的檔案語義,指的是POSIX規範。
S3指的是AWS提供的物件儲存服務以及相關介面。為方便描述,下文中以物件語義替代S3介面語義。
檔案語義和物件語義存在比較多的差異。

物件語義不支援檔案語義的部分特性,比如:

  • 目錄的操作,建立、刪除、修改名稱。
  • 檔案的部分操作,追加寫、隨機寫、修改名稱等。
  • 檔案的後設資料,比如:
    • 時間欄位,即crtime/ctime/mtime/atime。
    • 使用者和組,即uid/gid。
    • 許可權,即UGO和ACL。
    • 檔案的擴充套件屬性。
    • 硬連結。
    • 軟連結。
    • 鎖。

檔案語義不支援物件語義的部分特性,比如:

  • Etag,檔案語義中沒有定義相關資訊。
  • 生命週期管理。
  • 桶策略。
  • 多版本。
  • 物件的後設資料,即:
    • 系統後設資料,即標準HTTP頭部。
    • 使用者自定義後設資料,即命名為x-amz-meta-*的HTTP頭部。
    • 物件tagging,即命名為x-amz-tagging的HTTP頭部。

部分存在差異的語義,比如:

  • WORM,檔案語義和物件語義的實現,由於前述差異,具體實現和保護範圍可能存在一定的差異。
  • 檔案的建立。依據物件語義,儲存物件的操作是一個原子行為,包含資料、後設資料一併寫入,要麼成功、要麼失敗,只要上傳物件的介面返回了成功,即表示物件建立成功。而依據檔案語義,儲存檔案的操作,涉及開啟、寫入資料、寫入後設資料、關閉檔案等操作,並不是原子行為,寫入資料的過程中可能會被中斷,但由於檔案開啟成功,因此會出現資料不一致的現象。
  • 目錄,物件語義對目錄的支援非常有限,而檔案語義則提供了豐富的API。

物件語義中,使用物件來表示客戶的資料,在儲存和管理物件時,放棄了目錄的概念,所有的物件均以展平的形式儲存,在使用檔案語義實現物件語義時,需要對目錄做特殊的處理。
在檔案語義中,/有特殊含義,表示目錄的分隔符,因此一般不允許在目錄名或者檔名中使用。
AWS S3定義的規範中,/是普通字元,允許在物件名中使用。

做個實驗,登入Linux環境的控制檯,執行如下命令,輸出如下:

$ ll a.py
-rw-r--r-- 1 jackie docker 138 3月  29 21:47 a.py
$ mkdir a.py
mkdir: cannot create directory ‘a.py’: File exists
$ mkdir a.py/
mkdir: cannot create directory ‘a.py/’: File exists

依據物件語義,a.pya.py/是不同的物件,但在檔案語義下,a.py存在,則阻塞目錄a.py的建立操作。

依據檔案語義,刪除目錄即類似rm -rf /path/to/delete時,目錄和目錄下的所有的檔案、目錄均會被刪除。
考慮到本操作並不是一個原子操作,因此使用檔案語義實現物件語義的刪除操作時,會有比較多的注意事項。

思考點

  • 刪除目錄時,目錄下的物件,需要一併刪除。假如物件數量比較多時,則刪除操作將比較耗時。
  • 目錄下假如存在未合併的多段物件,是否一併刪除。
  • 目錄下假如僅有一個物件,使用物件語義的刪除介面,將該物件刪除時,目錄是否需要被刪除。
  • 先上傳目錄,上傳一個物件至該目錄下,使用物件語義的刪除介面,將該物件刪除時,目錄是否需要被刪除。
  • 手工上傳的目錄,在列舉物件時,是否作為一個物件在列舉結果中出現。
  • 如前所述,檔案主義並不支援物件主義的Etag,因此在實現上傳物件的操作時,需要計算並保留Etag值。
    • 儲存物件的資料的操作,計算MD5值的操作,二者需要保持進度一致,避免MD5值計算結果不正確,或者耗時過久,影響上傳操作的效能。
    • Etag儲存的位置。
  • 物件後設資料的儲存位置,依據語義,需要和資料一起儲存。
    • 後設資料儲存的位置。
    • 操作的原子性。
  • 物件語義寫入物件時,檔案的後設資料,應當如何填值。如前述,不支援的後設資料,如下:
    • 時間欄位,即crtime/ctime/mtime/atime。
    • 使用者和組,即uid/gid。
    • 許可權,即UGO和ACL。

相關文章