基础概念
object/part/
一个 RGW Object 由 N 个 part 组成,每个 part 由 M 个 strip 组成。对于简单上传,我们认为 N 为 1, part number 为 0。对于分块上传,我们认为每块就是一个 part,part number 也是相对应的 1~N。
对于一个 part,会分为 M 个 strip,每个 strip 对应于一个 rados obj。第一个 strip 称之为 HEAD obj,其他 M-1 个strip 称之为 TAIL obj。一般情况下,对象的一些元数据都会保存在 HEAD 对象的 attr/omap 中。
如何从一个对象名找到该对象所有的 part 和 strip 呢? RGW 通过 manifest 类来实现,manifest 会描述对象每个区间的数据分别由什么对象存储。在用户读取对象 foo 的时候,RGW 直接定位到同名的 HEAD obj(名字为 <bucket_id>_<obj_id>
),并读取该对象的 attr,拿到 manifest 数据。通过 manifest 可以得到文件由哪些 strip 组成,并分别去读取这些 strip obj,返回给用户。
atomic upload
atomic upload 是在一次请求内完成的上传操作,属于实现比较清晰的。对于 atomic upload 的对象看成 part 为1,part number 为 0 的情况。在实际的数据存储层(RADOS)上,会有一个名字为 <bucket_id>_<obj_name>
的 head 对象,以及若干个在 shadow namespace 下的 tail 对象,名字为 <bucket_id>.1__shadow_.<prefix_id>_<strip_num>
,如
9b60b3ba-81d5-4319-9092-a7b1921a3491.4240.1__shadow_.09YONY-GM_tn2FiW3e92YOHQ7qX-fE9_.1_1
。该对象所有的元数据都存储在 head obj 的 attr 中,包括 manifest 信息。
multipart upload
multipart upload 是经过 InitMultipart, N*UploadPart, CompleteMultipart
多个请求来完成的上传操作,比较复杂。与 atomic upload 不同的是,multipart upload 额外使用了一个 extra pool 来存储关于本次上传的分块信息, rgw_obj(bucket, oid+upload_id+”meta”)
对象会在 omap 中存储每个分块对应的 RGWUploadPartInfo
信息,RGWUploadPartInfo
中包含了每个分块的 manifest。在最终 CompleteMultipart 时,合并 mp meta obj 上所有分块的 manifest 数据,存储到 head obj 的 attr 中,并删除 mp meta obj。
因为,对于一个 multipart upload 的对象,会有一个同名的 head obj,每个 part 会有若干个对象组成,这些对象中第一个位于 multi namespace,其它位于 shadow namespace。