如下是官方文档中针对元数据的说明。
After you upload the object, you cannot modify object metadata. The only way to modify object metadata is to make a copy of the object and set the metadata.
对象的元数据仅在上传对象时或者复制对象时支持修改,在某些场景下使用不方便,因此提供更新元数据能力成为一种刚需。
本文有如下假定:
- 对象存储服务基于文件语义实现。
接口定义
依据前述,业界主流对象存储服务比如AWS S3并未定义修改对象元数据的操作,而国内的各家公有云对象存储服务,提供了对象的修改对象元数据的操作。
国内的公有云对象存储服务,相关操作的文档的链接(排名不分先后),如下:
- 华为云OBS
- 火山引擎
以华为云OBS的修改对象元数据为例,接口定义如下:
PUT /ObjectName?metadata HTTP/1.1
Host: bucketname.obs.region.myhuaweicloud.com
Content-Type: application/xml
Content-Length: length
Authorization: authorization
Date: date
<Optional Additional Header>
本接口的关键参数,如下:
- 对象名,指定修改元数据的对象名。
- 操作名,参数名为
metadata
,不需要指定参数值。 - 对象版本,参数名为
versionId
,依据实际情况指定。 - 操作指标,HTTP头部
x-obs-metadata-directive
,支持REPLACE_NEW
或REPLACE
。
本接口允许修改的元数据,比如:
- HTTP协议的标准头部
Cache-Control
Expires
Content-Encoding
Content-Disposition
Content-Type
Content-Language
- 用户元数据
x-obs-website-redirect-location
x-obs-meta-*
- 系统元数据
x-obs-storage-class
x-obs-expires
考虑到对象的tagging支持修改,因此不需要在本接口中再提供额外的实现。
实现思路
ETag
参考AWS S3数据一致性,ETag
基于对象的数据,使用MD5
算法计算得到。
修改元数据的操作不涉及数据的变更,因此无需更新MD5
值。
多版本
按照AWS S3多版本中的说明,多版本特性的开关作用在桶级,包含如下状态:
Buckets can be in one of three states:
- Unversioned (the default)
- Versioning-enabled
- Versioning-suspended
修改元数据的操作不涉及数据的变更,因此不涉及对象版本的数据的变更。
分级
参考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:ObjectMetadataUpdated:Put
。
依据AWS S3 消息格式,为了适配修改元数据操作,可以考虑在object中增加扩展对象metadata,使用KV格式,用于说明修改元数据操作。
在官方样例基础上增加必要的字段,得到如下样例:
{"Records":[{"eventVersion":"2.2","eventSource":"aws:s3","awsRegion":"us-west-2","eventTime":"The time, in ISO-8601 format, for example, 1970-01-01T00:00:00.000Z, when Amazon S3 finished processing the request","eventName":"event-type","userIdentity":{"principalId":"Amazon-customer-ID-of-the-user-who-caused-the-event"},"requestParameters":{"sourceIPAddress":"ip-address-where-request-came-from"},"responseElements":{"x-amz-request-id":"Amazon S3 generated request ID","x-amz-id-2":"Amazon S3 host that processed the request"},"s3":{"s3SchemaVersion":"1.0","configurationId":"ID found in the bucket notification configuration","bucket":{"name":"bucket-name","ownerIdentity":{"principalId":"Amazon-customer-ID-of-the-bucket-owner"},"arn":"bucket-ARN"},"object":{"key":"object-key","size":"object-size in bytes","eTag":"object eTag","versionId":"object version if bucket is versioning-enabled, otherwise null","sequencer": "a string representation of a hexadecimal value used to determine event sequence, only used with PUTs and DELETEs","metadata":[{name:"Cache-Control",value:""},{name:"Expires",value:""},{name:"Content-Encoding",value:""},{name:"Content-Disposition",value:""},{name:"Content-Type",value:""},{name:"Content-Language",value:""}]}}}]
}
并发一致性
依据AWS S3 data consistency model的说明,对象存储服务提供read-after-write
的模型。
当多客户端对相同对象并发的发起修改元数据的操作时,以最后一次请求的操作结果为准。