注意
本文档适用于 Ceph 的开发版本。
RADOS Gateway 数据布局
尽管源代码是最终指南,但本文档旨在帮助用户和新开发者快速了解实现细节。
简介
Swift 将用户对象收集到*容器*中,我们将其与 S3 术语*桶*互换使用,因此我们说 RGW 的桶实现了 Swift 容器。
本文档不考虑 RGW 如何对这些结构进行*操作*,例如使用 encode() 和 decode() 方法进行序列化。
概念视图
尽管 RADOS 只了解池和对象及其 xattrs 和 omap[1],但从概念上讲,RGW 维护三种类型的信息:元数据、桶索引和(有效载荷)数据。
元数据
RGW 存储多种类型的元数据。可以使用以下命令显示类型列表。截至 2025 年 4 月的类型如下所示
radosgw-admin metadata list
[
"account",
"bucket",
"bucket.instance",
"group",
"otp",
"roles",
"topic",
"user"
]
使用以下形式的命令来检查元数据条目
radosgw-admin metadata list
radosgw-admin metadata list bucket
radosgw-admin metadata list bucket.instance
radosgw-admin metadata list user
radosgw-admin metadata get bucket:<bucket>
radosgw-admin metadata get bucket.instance:<bucket>:<bucket_id>
radosgw-admin metadata get user:<user> # get or set
变量用于上述命令示例;发出命令时必须替换您的特定值
user:保存用户信息bucket:保存桶名称和桶实例 ID 之间的映射bucket.instance:保存桶实例信息[2]
每个元数据条目都保存在单个 RADOS 对象上。有关实现细节,请参见下文。
请注意,此元数据未编入索引。列出元数据部分时,我们对包含池执行 RADOS pgls 操作。
桶索引
桶索引是一种不同类型的元数据,并单独保存。桶索引保存附加到 RADOS 对象的键值映射。默认情况下,每个桶是一个 RADOS 对象,但自 Hammer 版本以来,可以将该映射分片到多个 RADOS 对象上。映射本身保存在 omap 中,与每个 RADOS 对象关联。每个 omap 的键是对象的名称,值包含该对象的一些基本元数据——列出桶时显示的元数据。此外,每个 omap 都有一个标头,我们在该标头中保留一些桶核算元数据(对象数、总大小等)。
请注意,我们还在桶索引中保存了其他信息,这些信息保存在其他键命名空间中。我们可以在那里保存桶索引日志,对于版本化对象,我们还会在其他键上保存更多信息。
数据
每个 RGW 对象的对象数据保存在一个或多个 RADOS 对象中。
对象查找路径
访问 S3/Swift 对象时,REST API 会向 RGW 提供三个参数:帐户信息(S3 中的访问密钥或 Swift 中的帐户名称)、桶或容器名称以及对象名称(或键)。目前,RGW 仅使用帐户信息来查找用户 ID 和进行访问控制。只有桶名称和对象键用于在池中寻址对象。
RGW 中的用户 ID 是一个字符串,通常是来自用户凭据的实际用户名,而不是哈希或映射的标识符。
访问用户数据时,用户记录将从池 default.rgw.meta 中命名为 <user_id> 且命名空间为 users.uid 的对象中加载。
桶名称在池 default.rgw.meta 中表示,命名空间为 root。加载桶记录以获取所谓的标记(marker),该标记充当桶 ID。
S3/Swift 对象位于名为 default.rgw.buckets.data 的池中。RADOS 对象名称为 <marker>_<key>,例如 default.7593.4_image.png,其中标记是 default.7593.4,键是 image.png。由于这些串联的名称没有被解析,只是向下传递给 RADOS,因此分隔符的选择并不重要,也不会引起歧义。出于同样的原因,对象名称(键)中允许使用斜杠。
可以创建多个数据池,并使不同用户的桶默认在不同的 RADOS 池中创建,从而提供必要的扩展性。这些池的布局和命名由“策略”设置控制。[3]
一个 RGW 对象可能包含多个 RADOS 对象,其中第一个是 HEAD,它包含元数据,包括清单、ACL、内容类型、ETag 和用户定义的元数据。元数据存储在 xattrs 中。为了效率和原子性,HEAD 对象还可以内联高达 rgw_max_chunk_size 的对象数据。这使得分层策略很方便:索引池必须是复制的(不能是 EC),并且应该放置在快速 SSD OSD 上。对于小/热 RGW 对象和较大的、温/冷 RGW 对象(例如视频文件)的混合,较大的对象将自动放置在 buckets.data 池中,该池可以是 EC 和/或较慢的存储(例如 HDD 或 QLC SSD)。
清单描述了每个 RGW 对象如何在 RADOS 对象中布局。
桶和对象列表
属于给定用户的桶列在池 default.rgw.meta 中名为 <user_id>.buckets(例如 foo.buckets)且命名空间为 users.uid 的 RADOS 对象的 omap 中。在列出桶、更新桶内容以及更新和检索桶统计信息(例如配额)时访问这些对象。
有关这些 omap 条目的值,请参阅用户可见的编码类 cls_user_bucket_entry 及其嵌套类 cls_user_bucket。
这些列表与名为 .rgw 的池中的桶保持一致。
属于给定桶的对象列在桶索引中,如上文“桶索引”小节所述。索引对象的默认命名是池 default.rgw.buckets.index 中的 .dir.<marker>。
脚注
[1] Omap 是一个与对象关联的键值存储,其方式类似于扩展属性 (XATTRs) 与 POSIX 文件关联的方式。对象的 omap 在物理上不与对象的有效载荷数据共存,并且其精确实现对于 RGW 守护程序是不可见的且无关紧要。
[2] 在 Dumpling 版本之前,“bucket.instance”元数据不存在,“bucket”元数据包含其信息。在旧安装中可能会遇到此类桶。
[3] 池名称在 Infernalis 版本中发生了变化。如果您正在查看较旧的设置,某些细节可能会有所不同。特别是,现在合并到 default.root.meta 池中的每个命名空间都有一个不同的池。
附录:概要
已知池
.rgw.root区域、区域和全局信息记录,每个对象一条。
<zone>.rgw.controlnotify.<N>
<zone>.rgw.meta具有不同类型元数据的多个命名空间
- 命名空间:
root <bucket>
.bucket.meta.<bucket>:<marker># 见 put_bucket_instance_info()租户用于区分桶,但不区分桶实例。示例
.bucket.meta.prodtx:test%25star:default.84099.6 .bucket.meta.testcont:default.4126.1 .bucket.meta.prodtx:testcont:default.84099.4 prodtx/testcont prodtx/test%25star testcont
- 命名空间:
users.uid 在“<user>”对象中包含*每个用户*信息 (RGWUserInfo),并在“<user>.buckets”对象的 omaps 中包含*每个用户*的桶列表。“<user>”可以包含租户(如果非空),例如
prodtx$prodt test2.buckets prodtx$prodt.buckets test2
- 命名空间:
users.email 不重要
- 命名空间:
users.keys 示例:
47UA98JSTJZ9YAN3OS3O这允许
radosgw在身份验证期间通过其访问密钥查找用户。- 命名空间:
users.swift test:tester
- 命名空间:
<zone>.rgw.buckets.index对象命名为
.dir.<marker>:每个对象包含一个桶索引。如果索引被分片,则每个分片在标记后附加分片索引。<zone>.rgw.buckets.data示例:
default.7593.4__shadow_.488urDFerTYXavx4yAd-Op8mxehnvTI_1<marker>_<key>
标记的一个示例是 default.16004.1 或 default.7593.4。当前格式为 <zone>.<instance_id>.<bucket_id>。但是一旦生成,标记就不会再次解析,因此其格式将来可能会自由更改。