2. RGWData
RGW对象数据存储在 {zone}.rgw.buckets.data池里,一个 RGW对象包含一个或多个 RADOS对象。
当 RGW收到写请求时,会基于 rgw_obj_stripe_size配置的值(默认为4MB)将数据切分为 stripe,并基于 rgw_max_chunk_size配置(默认为 4MB)将这些stripes划分为更小的 chunks,并将这些 chunks写入 RADOS集群。
第一个 chunk写入时会创建 Head对象,随后的 chunks作为tail 追加到对象后面写入。其中 Head对象包含了对象的一些元数据信息,如 ACL、manifest、etag等,作为 xattr保存。Head 对象本身可以包含 4MB 的数据。如果对象大于 4MB,就会生成tail 对象。
Head对象的 manifest 描述了对象的布局信息。查看对象的 xattr和 manifest,可使用如下命令。
# ./bin/rados listxattr -p default.rgw.buckets.data 54dba15f-9c2e-40ea-8b87-fc5f2eb01236.154118.1_ceph.conf
user.rgw.acluser.rgw.content_typeuser.rgw.etaguser.rgw.idtaguser.rgw.manifestuser.rgw.pg_veruser.rgw.source_zoneuser.rgw.storage_classuser.rgw.tail_tag
user.rgw.x-amz-content-sha256user.rgw.x-amz-date
user.rgw.x-amz-meta-s3cmd-attrs
#./bin/ceph-dencoderimportmanifest.txttypeRGWObjManifestdecodedump_json
{
"objs":[]
"obj_size": 6775"explicit_objs": "false""head_size":6775
"max_head_size":4194304
"prefix":".dhrTwsaLcBPQOYPeIx2bImXjxO_WCKk_"
"rules": [
{
"key": 0
"val": {
"start_part_num":0
"start_ofs":4194304
"part_size":0
"stripe_max_size":4194304
"override_prefix":""
}
}
]
"tail_instance": """tail_placement":{
"bucket": {
"name":"john-bkt1"
"marker": "54dba15f-9c2e-40ea-8b87-fc5f2eb01236.154118.1""bucket_id": "54dba15f-9c2e-40ea-8b87-fc5f2eb01236.154118.1""tenant":""
"explicit_placement": {"data_pool": """data_extra_pool": """index_pool":""
}
}
"placement_rule":"default-placement"
}
"begin_iter": {"part_ofs":0
"stripe_ofs":0
"ofs": 0
"stripe_size":6775
"cur_part_id":0
"cur_stripe": 0"cur_override_prefix": """location":{
"placement_rule":"default-placement"
"obj": {
"bucket": {
"name":"john-bkt1"
"marker": "54dba15f-9c2e-40ea-8b87-fc5f2eb01236.154118.1""bucket_id": "54dba15f-9c2e-40ea-8b87-fc5f2eb01236.154118.1""tenant":""
"explicit_placement": {"data_pool": """data_extra_pool": """index_pool":""
}
}
"key": {
"name":"ceph.conf"
"instance": ""
"ns": ""
}
}
"raw_obj":{
"pool": ""
"oid”: ""
"loc": ""
}
"is_raw":false
}
}
"end_iter": {"part_ofs":4194304
"stripe_ofs":0
"ofs":6775
"stripe_size":6775
"cur_part_id":0
"cur_stripe": 0"cur_override_prefix": """location":{
"placement_rule":"default-placement"
"obj": {
"bucket": {
"name":"john-bkt1"
"marker": "54dba15f-9c2e-40ea-8b87-fc5f2eb01236.154118.1""bucket_id": "54dba15f-9c2e-40ea-8b87-fc5f2eb01236.154118.1""tenant":""
"explicit_placement": {"data_pool": """data_extra_pool": """index_pool":""
}
}
"key": {
"name":"ceph.conf"
"instance":""
"ns":""
}
}
"raw_obj":{
"pool":""
"oid":""
"loc":""
}
"is_raw":false
}
}
}
RGW中的对象对应RADOS对象(一对多关系),对象上传分整体上传和分段上传,不同的上传方式,对应 RADOS对象的方式不同。
首先介绍 3个概念。
◆ rgw_max_chunk_size
RGW下发至 RADOS集群的单个 I/O的大小, 同时也决定了应用对象分成多个RADOS对象时首对象的大小。
◆ rgw_obj_stripe_size
条带大小,也是 RADOS对象最大大小,如果大于rgw_max_chunk_size的对象文件,后续部分会根据这个参数切成多个RADOS对象。
◆ rgwobjectmanifest
管理应用对象和 RADOS 对象的对应关系。
基于以上概念,我们分别介绍普通上传以及分块上传。普通上传的流程如下。
(1) 当对象大小小于等于 rgw_max_chunk_size 时,用户上传的一个对象只对应一个RADOS对象,该RADOS 对象以对象名称命名,对象元数据也保存在该RADOS对象的扩展属性中。
(2) 当对象大小大于 rgw_max_chunk_size 时,对象被划分为一个大小等于分块大小的head以及多个大小等于 rgw_obj_stripe_size 的中间对象,和一个大小小于或等于 rgw_obj_stripe_size的 tail对象。head 以对象名称命名,该对象的数据部分保存了对象前 rgw_max_chunk_size字节的数据,扩展属性部分保存了对象的元数据信息和 manifest信息。中间对象和tail对象保存对象剩余的数据,对象名称为:''shadow_'+ '.' + '32bit随机字符串'
+ '_' + ' 条带编号',其中条带编号从1开始。分块上传的流程如下。
(1) RGW根据条带大小 rgw_obj_stripe_size将对象的每一个分块分成多个 RADOS对象,每个分块的第一个 RADOS 对象名称为:'_multipart_'+ ' 用户上传对象名称 ' + ' 分块上传 ID' + ' 分段编号',其余对象的名称为:'_shadow_' + ' 用户上传对象名称' + ' 分块上传 ID'+ ' 分段编号' + '_' + ' 条带编号'。
(2) 当所有的分块上传结束后,RGW会从 data_extra_pool 中的分块上传的临时对象中读取各个分段信息,将各分段的 manifest信息组成一个 manifest;然后生成一个新的RADOS对象,即 head 对象,用来保存分块上传的对象的元数据信息和 manifest信息。