注意
本文档适用于 Ceph 开发版本。
快照
概述
Rados 支持两种相关的快照机制:
存储池快照: 快照隐式应用于存储池中的所有对象
自管理快照: 用户必须在每次写入时提供当前的SnapContext。
这两种机制是互斥的,特定存储池上只能使用其中一种。
The SnapContext是当前为对象定义的快照集,以及最新的快照(即seq)从 mon 请求用于排序目的(一个SnapContext更新的seq被认为是更近的)。
从 OSD 的角度来看,存储池快照和自管理快照之间的区别在于SnapContext是否通过客户端的 MOSDOp 到达 OSD,还是通过最新的 OSDMap 到达。
请参阅manifest.rst for more information.
磁盘结构
每个 PG 集合中的对象都有一个head对象,并且可能有一组clone对象。head(对象唯一可写入的版本),snap 字段设置为 CEPH_NOSNAP。对于克隆,snap 字段设置为在其创建时seq的SnapContext。clone之前是否带有快照 ID 标记了最新的快照,该快照在SnapContext中表示。如果是这样,那么在写入时间和最后一次克隆时间之间至少发生了一次快照。因此,在进行变异之前,OSD 为服务快照之间的读取创建一个新的克隆,这些快照 ID 在最后一次克隆和最新的快照 ID 之间。
The head对象包含一个SnapSet编码在属性中,它跟踪
对象定义的完整快照集
当前存在的完整克隆集
克隆之间的重叠区间,用于跟踪空间使用情况
克隆大小
The head在还有克隆存在时不能被删除。相反,它被标记为 whiteout (object_info_t::FLAG_WHITEOUT
) 以便存放它包含的SnapSet。head对象不再在逻辑上存在。
参考:should_whiteout()
Additionally, theobject_info_t在每个克隆上包括一个快照向量,该快照向量定义了克隆。
快照移除
要删除一个快照,向集群发出请求以将快照 ID 添加到已清除快照的列表中(在监控器 cluster to add the snapshot id to the list of purged snaps (or to remove it from the set of pool snaps in the case of 存储池快照的情况下,从存储池快照集中删除它)。在任何一种情况下,PG将快照添加到其snap_trimq以进行修剪。
当所有快照都被删除时,可以删除克隆。为了确定在快照删除时可能需要删除哪些克隆,我们维护一个从快照到hobject_t的映射,使用SnapMapper.
见 PrimaryLogPG::SnapTrimmer, SnapMapper
此修剪由 snap_trim_wq 异步执行,同时 PG 保持干净且未进行 scrubbing。
PG::snap_trimq 中下一个快照被选中进行修剪
我们从 PG::snap_mapper 确定下一个要修剪的对象。
我们还使用本地更新我们的SnapMapper实例,以包含对象的新快照。
包含对象修改的日志条目还包含新的快照集,副本使用它来更新其自己的SnapMapper instance.
主要副本共享信息,副本持久化新的
恢复
由于修剪操作使用 repops 和日志条目实现,正常的 PG 对等和恢复维护快照修剪操作,但需要注意推送和删除操作需要更新本地SnapMapper实例。如果 purged_snaps 更新丢失,我们只需重新修剪一个现在为空的快照。
SnapMapper
SnapMapper是基于 map_cacher<string, bufferlist> 实现的,它提供了一个接口,用于在后备存储(如文件系统)上使用异步事务。虽然事务不完整,但 map_cacher 实例缓冲不稳定键,允许一致访问,而无需刷新文件存储。SnapMapper提供两个映射:
hobject_t -> set<snapid_t>: 存储每个克隆对象的快照集
snapid_t -> hobject_t: 存储具有快照作为其快照之一的 hobject 集合
假设:有很多 hobject 和相对较少的快照。第一个编码具有对象作为键的字符串化和快照集作为值的编码。第二个映射,因为单个快照可能有多个 hobject,因此存储为形式为 stringify(snap)_stringify(object) 的键集合,其中 stringify(snap) 是固定长度的。这些键具有作为值的 bufferlist 编码对SnapMapper提供了用于过滤单个 SnapMapper 键空间中属于该 PG 的对象的掩码。
分割
snapid_t -> hobject_t 键条目排列方式是,对于任何 PG,最多需要检查 8 个前缀才能确定特定快照中特定 PG 的所有 hobject。在拆分时,对父级要检查的前缀进行调整,以便仅 PG 中剩余的对象可见。子对象将立即具有正确的映射。
clone_overlap
每个 SnapSet 附加到head对象都包含克隆对象之间的重叠区间,以优化空间。clone_overlap
map 中,每个 map 元素存储快照 ID 和与下一个最新克隆的相应重叠。
参考以下使用 4 字节对象的示例:
object |
content |
---|---|
head |
[AAAA] |
listsnaps 输出如下:
cloneid |
snaps |
size定位特定驱动器容量: |
overlap |
---|---|---|---|
head |
4 |
在拍摄快照(ID 1)并重新编写对象的前 2 个字节后,创建的克隆将与新的head对象在其最后 2 个字节重叠。
object |
content |
---|---|
head |
[BBAA] |
clone ID 1 |
[AAAA] |
cloneid |
snaps |
size定位特定驱动器容量: |
overlap |
---|---|---|---|
1 |
1 |
4 |
[2~2] |
head |
4 |
通过拍摄另一个快照(ID 2)并且这次只重新编写对象的前 1 个字节,创建的克隆(ID 2)将与新的head对象在其最后 3 个字节重叠。
object |
content |
---|---|
head |
[CBAA] |
clone ID 2 |
[BBAA] |
clone ID 1 |
[AAAA] |
cloneid |
snaps |
size定位特定驱动器容量: |
overlap |
---|---|---|---|
1 |
1 |
4 |
[2~2] |
2 |
2 |
4 |
[1~3] |
head |
4 |
如果未设置head对象将通过重新编写 4 个字节完全重写,唯一剩余的重叠将是两个克隆之间的重叠。
object |
content |
---|---|
head |
[DDDD] |
clone ID 2 |
[BBAA] |
clone ID 1 |
[AAAA] |
cloneid |
snaps |
size定位特定驱动器容量: |
overlap |
---|---|---|---|
1 |
1 |
4 |
[2~2] |
2 |
2 |
4 |
|
head |
4 |
最后,在最后一个快照(ID 2)被删除并且快照修剪启动后,将不再有任何重叠区间:
object |
content |
---|---|
head |
[DDDD] |
clone ID 1 |
[AAAA] |
cloneid |
snaps |
size定位特定驱动器容量: |
overlap |
---|---|---|---|
1 |
1 |
4 |
|
head |
4 |
由 Ceph 基金会带给您
Ceph 文档是一个社区资源,由非盈利的 Ceph 基金会资助和托管Ceph Foundation. 如果您想支持这一点和我们的其他工作,请考虑加入现在加入.