類似檔案的追加寫操作,在物件的末尾增加新的資料內容。
本文有如下假定:
- 物件儲存服務基於檔案語義實現。
- 使用PUT方式上傳的物件,內部使用一個檔案和對應的後設資料來承載。
- 使用多段方式上傳的物件,內部使用多個段檔案、後設資料來承載,其中每個段檔案可管理獨有的後設資料。
下面討論追加寫操作時的方案和注意事項。
介面定義
業界主流物件儲存服務比如AWS S3並未定義追加寫操作,而國內的各家公有云物件儲存服務基於物件語義和檔案語義的理解,提供了物件的追加寫操作。
國內的公有云物件儲存服務,提供的追加寫操作,相關文件的連結(排名不分先後),如下:
- 阿里雲OSS
- 華為雲OBS
- 騰訊雲COS
- 火山引擎
以阿里雲OSS的AppendObject為例,介面定義如下:
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的約束,但保持最大規格的約束。
加密儲存
可行的實現方案,如下:
-
方案一
- 校驗加密演算法,保證加密方式一致。
- 解密物件已有的資料。
- 和追加到末尾的資料。
- 完整執行加密操作。
- 更新後設資料。
- 儲存後設資料和資料。
-
方案二
- 校驗加密演算法,保證加密方式一致。
- 解密後設資料。
- 加密本次追加到末尾的資料。
- 更新後設資料。
- 儲存後設資料和資料。
方案二中,在物件的後設資料中需要記錄每次追加資料的明文、密文的長度,以及加密演算法需要保留的資訊。
PUT方式上傳物件的多段方案
參照多段物件,將追加寫的資料當成一個新的段,原有的物件當成多段方式上傳的第一個段。
物件規格
維持多段物件的限制,在介面中增加必要的校驗,即
- 單個段的上限為5GiB。
- 段的數量維持在10000個。
按照上述限制,物件的大小,至多為約48.8TiB。
加密儲存
可行的實現方案,如下:
- 校驗加密演算法,保證加密方式一致。
- 解密後設資料。
- 本次追加寫的資料,作為單獨一個段,執行加密。
- 更新後設資料。
- 儲存後設資料和資料。
多段方式上傳的物件的檔案追加寫方案
參照檔案的追加寫,即把物件的最後一個段當成檔案,將追加寫操作的資料追加到最後一個段的資料的尾部。
物件規格
依據多段物件的限制,如下:
- 單個段的上限為5GiB。
- 段的數量維持在10000個。
假如直接在多段物件的最後一個段執行追加寫操作,如維持上述約束,則可追加寫的資料的總和不超過5GiB,應用場景受限。
假如允許多次追加操作後的資料量超出5GiB,則可能破壞物件語義。
加密儲存
可行的實現方案,如下:
-
方案一
- 校驗加密演算法,保證加密方式一致。
- 解密物件的最後一個段的已有的資料。
- 和追加到末尾的資料。
- 完整執行加密操作。
- 更新後設資料。
- 儲存後設資料和物件的最後一個段。
-
方案二
- 校驗加密演算法,保證加密方式一致。
- 解密物件的最後一個段的後設資料。
- 加密本次追加到末尾的資料。
- 更新物件的最後一個段的後設資料。
- 儲存物件的最後一個段的後設資料和資料。
方案二中,在物件的最後一個段的後設資料中需要記錄每次追加資料的明文、密文的長度,以及加密演算法需要保留的資訊。
多段方式上傳的物件的多段方案
參照多段物件,將追加寫的資料當成一個新的段,追加到物件的段的尾部。
物件規格
維持多段物件的限制,在介面中增加必要的校驗,即
- 單個段的上限為5GiB。
- 段的數量維持在10000個。
按照上述限制,物件的大小,至多為約48.8TiB。
加密儲存
可行的實現方案,如下:
- 校驗加密演算法,保證加密方式一致。
- 解密後設資料。
- 本次追加寫的資料,作為單獨一個段,執行加密。
- 更新後設資料。
- 儲存後設資料和資料。
參考資料
物件儲存
- AWS S3
- 阿里雲OSS
- 華為雲OBS
- 騰訊雲COS
- 火山引擎