依據AWS S3,沒有定義修改資料的操作,修改資料時,均需要重新上傳物件的資料和後設資料。
本文有如下假定:
- 物件儲存服務基於檔案語義實現。
介面定義
依據前述,業界主流物件儲存服務比如AWS S3並未定義修改物件資料的操作,而國內的各家公有云物件儲存服務,提供了物件的修改物件資料的操作。
國內的公有云物件儲存服務,相關操作的文件的連結(排名不分先後),如下:
- 華為雲OBS
以華為雲OBS的修改寫物件為例,介面定義如下:
PUT /ObjectName?modify&position=Position HTTP/1.1
Host: bucketname.obs.region.myhuaweicloud.com
Content-Type: type
Content-Length: length
Authorization: authorization
Date: date
<object Content>
本介面的關鍵引數,如下:
- 物件名,指定修改資料的物件名。
- 操作名,引數名為
modify
,不需要指定引數值。 - 修改位置,引數名為
position
,依據實際情況指定。 - 操作指標,HTTP頭部
Content-Length
,本次操作修改的資料的長度。
實現思路
修改資料的範圍
對於普通物件,即使用PUT或者複製方式上傳的物件,物件大小的範圍為[1, 5GiB]
,因此
- 假如
position
的位置小於1
或者大於5GiB
,則校驗失敗。 - 假如
Content-Length
的取值小於1
或者大於5GiB
,則校驗失敗。 - 假如
position
和Content-Length
的和大於5GiB
,則校驗失敗。
對於使用多段方式上傳的物件,涉及的API,如下:
- CreateMultipartUpload
- UploadPart
- UploadPartCopy
- CompleteMultipartUpload
段的數量上限為10000
,每個段大小的範圍為[1, 5GiB]
,因此物件整體的範圍可到達到[1, 48.8TiB]
,因此
- 假如
position
的位置小於1
或者大於48.8TiB
,則校驗失敗。 - 假如
Content-Length
的取值小於1
或者大於48.8TiB
,則校驗失敗。 - 假如
position
和Content-Length
的和大於48.8TiB
,則校驗失敗。
物件大小的規格,參見AWS S3文件。
ETag
參考AWS S3資料一致性,ETag
基於物件的資料,使用MD5
演算法計算得到。
服務端校驗資料一致的流程
- 客戶端使用本次上傳的資料,基於
MD5
演算法計算得到MD5
值X1
。 - 客戶端在請求中附帶的
Content-MD5
為使用本次資料計算到的MD5
值X1
。 - 物件儲存服務端收到資料後,基於
MD5
演算法計算得到本次操作的MD5
值X2
。 - 服務端執行
MD5
值X1
和X2
的比較。- 二者一致,則判定資料一致,本次寫入操作成功。
- 二者不一致,則判定資料不一致,本次寫入操作失敗。
- 服務端在返回的響應中增加
ETag
欄位,使用服務端計算的MD5
值X2
填充。
客戶端校驗資料一致的流程
- 客戶端發起請求,並在讀資料、寫資料的過程中,使用本次上傳的資料,基於
MD5
演算法計算得到MD5
值X1
。 - 物件儲存服務端收到資料後,基於
MD5
演算法計算得到本次操作的MD5
值X2
。 - 服務端在返回的響應中增加
ETag
欄位,使用服務端計算的MD5
值X2
填充。 - 客戶端使用本地計算的
X1
和服務端返回的ETag
進行比較。- 二者一致,則判定資料一致,本次寫入操作成功。
- 二者不一致,則判定資料不一致,本次寫入操作失敗。考慮到服務端已成功寫入,因此需要增加必要的修復措施。
服務端物件的MD5值
由於變更了部分資料,因此物件的ETag
值和資料已不一致,需要設計補救方案。
對於普通物件,即使用PUT或者複製方式上傳的物件,考慮在後臺任務中讀取全量資料,計算物件資料的MD5
值,儲存至ETag
欄位的值儲存下來。
對於使用多段方式上傳的物件,涉及的API,如下:
- CreateMultipartUpload
- UploadPart
- UploadPartCopy
- CompleteMultipartUpload
依據Checking object integrity的介紹,該類物件的ETag
值樣例為C9A5A6878D97B48CC965C1E41859F034-14
,由所有的段的MD5
值計算得到,因此修復操作相對複雜一些。
- 依據修改點起始位置
position
和Content-Length
計算涉及變化的段的清單。 - 依據最新的資料,計算涉及變化的段的
MD5
值。 - 使用所有的段的
MD5
值,按照多段物件的ETag
值的生成規則,重新計算,得到最終的結果。
物件儲存服務在實現時,有如下需求:
- 多段物件的系統後設資料中保留所有的段的清單。
- 段的後設資料中記錄自身的
MD5
值,資料的起始位置、段的長度。
多版本
按照AWS S3多版本中的說明,多版本特性的開關作用在桶級,包含如下狀態:
Buckets can be in one of three states:
- Unversioned (the default)
- Versioning-enabled
- Versioning-suspended
介面定義中未提供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:ObjectDataUpdated:Put
。
併發一致性
依據AWS S3 data consistency model的說明,物件儲存服務提供read-after-write
的模型。
當多客戶端對相同物件併發的發起修改資料的操作時,參照檔案語義,提供最終一致性。