物件業務的追加寫介面

jackieathome發表於2024-06-03

類似檔案的追加寫操作,在物件的末尾增加新的資料內容。

本文有如下假定:

  • 物件儲存服務基於檔案語義實現。
  • 使用PUT方式上傳的物件,內部使用一個檔案和對應的後設資料來承載。
  • 使用多段方式上傳的物件,內部使用多個段檔案、後設資料來承載,其中每個段檔案可管理獨有的後設資料。

下面討論追加寫操作時的方案和注意事項。

介面定義

業界主流物件儲存服務比如AWS S3並未定義追加寫操作,而國內的各家公有云物件儲存服務基於物件語義和檔案語義的理解,提供了物件的追加寫操作。

國內的公有云物件儲存服務,提供的追加寫操作,相關文件的連結(排名不分先後),如下:

  • 阿里雲OSS
  • 華為雲OBS
  • 騰訊雲COS
  • 火山引擎

阿里雲OSSAppendObject為例,介面定義如下:

POST /ObjectName?append&position=Position HTTP/1.1
Content-Length:ContentLength
Content-Type: ContentType
Host: BucketName.oss.aliyuncs.com
Date: GMT Date
Authorization: SignatureValue

本介面的關鍵引數,如下:

  • 物件名,指定執行追加寫操作的物件名。
  • 操作名,引數名為append,不需要指定引數值。
  • 追加寫的位置,引數名為position,引數值為追加寫的開始位置。
  • 資料的長度,使用HTTP頭部Content-Length承載。

另外允許更新物件的後設資料,物件的後設資料的說明見文件

實現思路

考慮到物件上傳特點的特點,可以劃分為PUT方式上傳的物件,和使用多段方式上傳的物件,因此在實現追加寫時,需要考慮這兩種物件和上傳方式的差異,借鑑實現思路。

對於PUT方式上傳的物件,實現追加寫時,可以考慮如下方案:

  • 參照檔案的追加寫,即把物件當成檔案,將追加寫操作的資料追加到物件的資料的尾部。
  • 參照多段物件,將追加寫的資料當成一個新的段,原有的物件當成多段方式上傳的第一個段。

對於多段方式上傳的物件,實現追加寫時,可以考慮如下方案:

  • 參照檔案的追加寫,即把物件的最後一個段當成檔案,將追加寫操作的資料追加到最後一個段的資料的尾部。
  • 參照多段物件,將追加寫的資料當成一個新的段,追加到物件的段的尾部。

下面從物件服務特性的角度,分別評估上述方案。

ETag

參考AWS S3資料一致性ETag基於物件的資料,使用MD5演算法計算得到。

客戶應用在請求的頭部增加Content-MD5,指定本次上傳資料的MD5值,或者物件資料整體的MD5值。

本次上傳資料的MD5

客戶應用在請求的頭部增加Content-MD5,指定本次上傳資料的MD5值。
物件儲存服務收到資料後,計算資料的MD5值,並和Content-MD5值對比:

  • 假如二者一致,則判定資料一致。
  • 假如二者不一致,則判定資料不一致。

物件儲存服務處理追加寫操作成功後,在返回的訊息中使用ETag欄位,返回服務端依據接收到的資料計算得到的MD5值,方便物件儲存的客戶應用執行客戶端的校驗。

本方案中,由於只需要計算追加的資料的MD5值,因此客戶應用並不需要獲得物件的完整資料。相應的,物件儲存的服務端同樣只需要計算追加的資料的MD5值,不需要讀取物件的完整資料,操作簡單。

物件資料整體的MD5
客戶應用在請求的頭部增加Content-MD5,指定物件資料整體的MD5值。
物件儲存服務收到資料後,需要讀取物件的資料,結合本次上傳的資料,一併計算,得到MD5值。然後和Content-MD5值對比:

  • 假如二者一致,則判定資料一致。
  • 假如二者不一致,則判定資料不一致。

物件儲存服務處理追加寫操作成功後,在返回的訊息中使用ETag欄位,返回服務端的物件的MD5值,方便物件儲存的客戶應用執行客戶端的校驗。

本方案中,由於需要計算完整物件的MD5值,因此客戶應用在執行追加寫操作前,本地需要獲得物件的全部資料,結合本次追加寫操作的資料,一起計算MD5值。相應的,物件儲存的服務端需要執行類似的操作,操作流程相對複雜,加大了服務端的負擔。

多版本

按照AWS S3多版本中的說明,多版本特性的開關作用在桶級,包含如下狀態:

Buckets can be in one of three states:

  • Unversioned (the default)
  • Versioning-enabled
  • Versioning-suspended

當未開啟多版本特性,即Unversioned,物件執行追加寫操作時,透過直接修改物件的資料來實現。

當開啟多版本特性,即Versioning-enabled,有如下選擇:

  • 當未指定版本號時,有如下選擇:
    • 當前版本為delete-marker,返回失敗。
    • 修改物件的當前版本。
    • 新增物件,資料包括原物件的資料和本次追加寫的資料。
  • 當指定版本號時,有如下選擇:
    • 指定版本是delete-marker,返回失敗。
    • 指定版本不是delete-marker,修改物件的指定版本。
    • 返回失敗,不允許修改歷史版本。

當暫停多版本特性,即Versioning-suspended,有如下選擇:

  • 當未指定版本號時,有如下選擇:
    • 當前版本為delete-marker,返回失敗。
    • 修改物件的當前版本。
  • 當指定版本號時,有如下選擇:
    • 指定版本是delete-marker,返回失敗。
    • 指定版本不是delete-marker,修改物件的指定版本。
    • 返回失敗,不允許修改歷史版本。

不過依據前述介面的定義,沒有定義versionId,推斷不支援修改歷史版本,因此可以不考慮這麼複雜的特性。

分級

參考AWS S3 歸檔AWS S3 分級中的說明,處於歸檔狀態的物件,需要先取回才能訪問。
顯而易見,此處為了維護物件語義,照顧物件儲存服務的實現,當物件處於歸檔狀態時,不允許透過呼叫追加寫介面來追加資料。

WORM

參考AWS S3 Object Lock中的說明,開啟WORM後:

  • 在保護期內的物件,不允許修改,不允許刪除。
  • 在保護期外的物件,不允許修改,允許刪除。

因此從維護物件語義的角度講,在保護期內的物件、保護期外的物件,均不允許透過呼叫追加寫介面來修改物件。

生命週期

參考AWS S3 Lifecycle,追加寫操作過程中,被操作的物件可能符合生命週期規則,從而被恰好正在執行的後臺任務刪除掉。
此時有如下選擇:

  • 生命週期的後臺任務具備更高的優先順序,提前中斷追加寫操作,正常刪除掉物件,物件儲存服務對客戶應用返回追加寫操作失敗。
  • 生命週期的後臺任務優先順序相對較低,跳過當前物件,待下次執行時再決策是否刪除。

資料加密

依據SSE-C的說明,客戶應用在執行PUT/GET/Head/Copy操作時,均需要提供加密資料的金鑰。

即在發起請求時,提供如下頭部:

  • x-amz-copy-source​-server-side​-encryption​-customer-algorithm
  • x-amz-copy-source​-server-side​-encryption​-customer-key
  • x-amz-copy-source-​server-side​-encryption​-customer-key-MD5

另外說明物件的後設資料和資料均被加密。

事件通知

依據AWS S3 事件通知中的說明,物件儲存服務可以提供事件通知,目前支援的事件型別見文件,顯然不包括追加寫操作,可以擴充套件事件名,比如:

  • s3:ObjectAppended:Put,使用PUT方式追加。
  • s3:ObjectAppended:Post,使用POST方式追加。

依據AWS S3 訊息格式,為了適配追加寫操作,可以考慮在object中增加擴充套件欄位,用於說明追加寫操作,比如:

  • sizeAppended,本次追加寫操作的資料量,單位為bytes
  • eTagAppended,本次追加寫操作的資料的MD5值。

併發一致性

依據AWS S3 data consistency model的說明,物件儲存服務提供read-after-write的模型。

當多客戶端對相同物件併發的發起追加寫操作時,實現方案較複雜,需要平衡語義、功能、效能等方面的訴求,設計實現方案。

方案的差異

PUT方式上傳物件的檔案追加寫方案

參照檔案的追加寫,即把物件當成檔案,將追加寫操作的資料追加到物件的資料的尾部。

物件規格
使用PUT方式上傳的物件,預設小於5G,因此實現時有兩種選擇,一是維持約束,將5G作為物件大小的上限,二是打破5G的約束,但保持最大規格的約束。

加密儲存
可行的實現方案,如下:

  • 方案一

    1. 校驗加密演算法,保證加密方式一致。
    2. 解密物件已有的資料。
    3. 和追加到末尾的資料。
    4. 完整執行加密操作。
    5. 更新後設資料。
    6. 儲存後設資料和資料。
  • 方案二

    1. 校驗加密演算法,保證加密方式一致。
    2. 解密後設資料。
    3. 加密本次追加到末尾的資料。
    4. 更新後設資料。
    5. 儲存後設資料和資料。

方案二中,在物件的後設資料中需要記錄每次追加資料的明文、密文的長度,以及加密演算法需要保留的資訊。

PUT方式上傳物件的多段方案

參照多段物件,將追加寫的資料當成一個新的段,原有的物件當成多段方式上傳的第一個段。

物件規格
維持多段物件的限制,在介面中增加必要的校驗,即

  • 單個段的上限為5GiB。
  • 段的數量維持在10000個。

按照上述限制,物件的大小,至多為約48.8TiB。

加密儲存
可行的實現方案,如下:

  1. 校驗加密演算法,保證加密方式一致。
  2. 解密後設資料。
  3. 本次追加寫的資料,作為單獨一個段,執行加密。
  4. 更新後設資料。
  5. 儲存後設資料和資料。

多段方式上傳的物件的檔案追加寫方案

參照檔案的追加寫,即把物件的最後一個段當成檔案,將追加寫操作的資料追加到最後一個段的資料的尾部。

物件規格
依據多段物件的限制,如下:

  • 單個段的上限為5GiB。
  • 段的數量維持在10000個。

假如直接在多段物件的最後一個段執行追加寫操作,如維持上述約束,則可追加寫的資料的總和不超過5GiB,應用場景受限。
假如允許多次追加操作後的資料量超出5GiB,則可能破壞物件語義。

加密儲存
可行的實現方案,如下:

  • 方案一

    1. 校驗加密演算法,保證加密方式一致。
    2. 解密物件的最後一個段的已有的資料。
    3. 和追加到末尾的資料。
    4. 完整執行加密操作。
    5. 更新後設資料。
    6. 儲存後設資料和物件的最後一個段。
  • 方案二

    1. 校驗加密演算法,保證加密方式一致。
    2. 解密物件的最後一個段的後設資料。
    3. 加密本次追加到末尾的資料。
    4. 更新物件的最後一個段的後設資料。
    5. 儲存物件的最後一個段的後設資料和資料。

方案二中,在物件的最後一個段的後設資料中需要記錄每次追加資料的明文、密文的長度,以及加密演算法需要保留的資訊。

多段方式上傳的物件的多段方案

參照多段物件,將追加寫的資料當成一個新的段,追加到物件的段的尾部。

物件規格
維持多段物件的限制,在介面中增加必要的校驗,即

  • 單個段的上限為5GiB。
  • 段的數量維持在10000個。

按照上述限制,物件的大小,至多為約48.8TiB。

加密儲存
可行的實現方案,如下:

  1. 校驗加密演算法,保證加密方式一致。
  2. 解密後設資料。
  3. 本次追加寫的資料,作為單獨一個段,執行加密。
  4. 更新後設資料。
  5. 儲存後設資料和資料。

參考資料

物件儲存

  • AWS S3
  • 阿里雲OSS
  • 華為雲OBS
  • 騰訊雲COS
  • 火山引擎

相關文章