注意
本文档适用于 Ceph 的开发版本。
Rados 存储桶索引
RGW 中的存储桶将其对象列表存储在存储桶索引中。每个索引条目只存储足够的元数据(大小、etag、mtime 等)以用于处理列出对象的 API 请求。这些 API 包括 S3 中的 ListObjectsV2 和 ListObjectVersions,以及 Swift 中的 GET Container。
注意
存储桶可以创建为“无索引”模式。此类存储桶没有索引,并且无法被列出。
一致性保证
RGW 保证对象操作的读写一致性。这意味着一旦客户端收到成功的写入请求响应,该写入的效果必须对后续的读取请求可见。
例如:如果 S3 客户端发送一个 PutObject 请求来覆盖一个现有对象,然后发送一个 GetObject 请求来读取它,RGW 决不能返回前一个对象的内容。它必须要么返回新对象的内容,要么返回一个后续对象写入或删除的结果。
此一致性保证适用于所有对象写入请求(PutObject、DeleteObject、PutObjectAcl 等)和所有对象读取请求(HeadObject、GetObject、ListObjectsV2 等)。
Rados 对象模型
S3/Swift 对象或“API 对象”作为 Rados 对象存储在 rgw.buckets.data 池中。每个 API 对象由一个 head 对象和零个或多个 tail 对象组成。存储桶索引对象存储在 rgw.buckets.index 池中。
写入对象时,其 head 对象最后写入。这充当了一个原子“提交”操作,使其对读取请求可见。
索引事务
为了保持存储桶索引一致性,所有对象写入或删除都必须相应地更新索引。由于 head 对象存储在与存储桶索引不同的 Rados 对象中,我们无法通过单个 Rados 操作原子地更新两者。为了满足列出操作的 一致性保证,我们必须使用三步存储桶索引事务来协调这两个对象写入
在存储桶索引对象上准备一个事务。
写入或删除 head 对象。
在存储桶索引对象上提交事务(如果第 2 步失败则取消事务)。
对象写入和删除可能会相互竞争,因此一个给定对象可能同时有多个已准备好的事务。如果存在任何未完成的事务,RGW 会将对象条目视为“待定”状态;否则视为“已完成”状态。
此事务在 src/rgw/driver/rados/rgw_rados.cc 中实现,对象写入对应 RGWRados::Object::Write::write_meta(),对象删除对应 RGWRados::Object::Delete::delete_obj()。存储桶索引操作在 src/cls/rgw/cls_rgw.cc 中实现,对应 rgw_bucket_prepare_op() 和 rgw_bucket_complete_op()。
列表显示
列出对象时,RGW 将从存储桶索引中读取所有条目(待定和已完成)。对于任何待定条目,它必须在将该条目包含在最终列表中之前检查 head 对象是否存在。
如果 RGW 在 索引事务 中途崩溃,索引条目可能会停留在这种“待定”状态。当存储桶列表遇到这些待定条目时,它还会将 head 对象的信息发送回存储桶索引,以便它可以更新条目并解决其过时的事务。此消息称为“dir suggest”(目录建议),因为存储桶索引将其视为提示或建议。
存储桶列表在 src/rgw/driver/rados/rgw_rados.cc 中实现,对应 RGWRados::Bucket::List::list_objects_ordered() 和 RGWRados::Bucket::List::list_objects_unordered()。RGWRados::check_disk_state() 是读取 head 对象并编码建议更改的部分。相应的存储桶索引操作在 src/cls/rgw/cls_rgw.cc 中实现,对应 rgw_bucket_list() 和 rgw_dir_suggest_changes()。
S3 对象版本控制
对于已启用版本控制的存储桶,存储桶索引包含每个对象版本和删除标记的条目。除了按对象名称对索引条目排序外,它还必须按从新到旧的顺序对同一名称的对象版本排序。
RGW 为每个对象版本在 rgw.buckets.data 池中存储一个 head 对象。此 Rados 对象的 oid 是对象名称及其版本 ID 的组合。
在 S3 中,对对象名称的 GET/HEAD 请求将为您提供该对象的“当前”版本。为了支持这一点,RGW 存储了一个额外的“对象逻辑头”(olh)对象,其 oid 仅包含对象名称,充当其当前版本 head 对象的间接引用。此间接引用逻辑在 src/rgw/driver/rados/rgw_rados.cc 中实现,对应 RGWRados::follow_olh()。
为了保持此 olh 对象与存储桶索引之间的一致性,索引为每个对象名称保留一个单独的“olh”条目。此条目存储对其版本的所有写入/删除的日志。在 src/rgw/driver/rados/rgw_rados.cc 中,RGWRados::apply_olh_log() 重放此日志,以保证此 olh 对象与存储桶索引收敛到相同的“当前”版本。