尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Ceph ECBackend 实现策略深度解析:EC 池写入、回滚与恢复管线设计

Ceph ECBackend 实现策略深度解析:EC 池写入、回滚与恢复管线设计 存储分布式文件系统对象存储后端高可用【免费下载链接】cephCeph is a distributed object, block, and file storage platform项目地址https://gitcode.com/gh_mirrors/ce/ceph点击查看免费下载Ceph 的 ECErasure Coding纠删码后端ECBackend承载了纠删码存储池在主 OSD 上的全部数据读写逻辑。本文以 ecbackend.rst 为核心结合 src/osd/ECBackend.h、src/osd/ECCommon.h、src/osd/ECExtentCache.h 等源码实现系统讲解 EC 池的操作约束、shard 寻址模型、整条带写与读改写RMW两条数据流、两阶段提交与回滚机制以及 ExtentCache 与 RMW 管线的并发控制。读完本文你将理解 ECBackend 为什么不能像复制后端那样自由覆盖写也能掌握其写入管线在源码中的完整落地形态。一、设计背景EC 池最初只允许可回滚的操作与复制replicated策略不同EC 策略把数据按条带stripe切分后分散到 KM 个 shard 上任何就地修改都会牵动多个分片的一致性。因此 ECBackend 的初始设计在没有启用 EC overwrites 调试开关的普通 EC 池上至今仍然成立将 EC 池的操作限制为可以方便地本地回滚的三种CEPH_OSD_OP_APPEND追加写追加操作可以本地回滚方法是在 PG 日志事件中附带追加前的对象大小。CEPH_OSD_OP_DELETE删除删除的回滚要求在所有副本都持久化删除事件之前保留被删对象。因此 EC 后端在向 filestore 写入对象时需要在 key 中包含对象创建时的版本号当所有副本都提交到删除该对象的日志事件之后旧版本对象才可被剪除prune。CEPH_OSD_OP_(SET|RM)ATTR设置/删除属性只要在日志中附带被设置/删除属性的旧值就可以在本地回滚这些操作。日志条目中包含一个描述如何本地撤销该操作的结构即 osd_types.h 中的TransactionInfo::LocalRollBack与回滚对应的正向执行结构为LocalRollForward。这一设计决定了 EC 池后续所有写入流程见两阶段提交小节都围绕可提交 可回滚来组织。二、PGTemp 与 CRUSH让 acting set 出现空洞与独立主分片在复制池中PG 的 acting set 里acting[0]就是主 OSD。但 EC 池的主分片不必占据第一个位置且为了在 backfill 新主 OSD 期间让一个已 up-to-date 的 OSD 继续服务请求主 OSD 需要能申请一个临时的 acting set 映射PGTemp。ECBackend 因此要求OSDMap::pg_to_*_osds需要单独返回 primary而不是一律假定acting[0]MOSDPGTemp及相关 OSD 结构需要能同时指定 primary 和 acting set。从源码看src/messages/MOSDPGTemp.h 中pg_temp为std::mappg_t, std::vectorint32_tacting set 以 int32 向量表达而主分片信息由 OSD 侧从OSDMap::get_primary_shard见 src/osd/OSDMap.h解析既有代码大量假设acting[0]即主分片、acting set 每个位置都有效需要清理因为 EC 的 acting set 可能含有空洞holes。三、区分 acting set 中的分片位置ghobject_t、coll_t 与 spg_t复制策略下 PG 的所有副本可互换而纠删码策略下acting set 中不同位置对应纠删码方案的不同分片chunk彼此不可互换。更糟的是CRUSH 可能把 chunk 2 写到一个已经存有旧 chunk 4 的 OSD 上。因此 OSD 与 PG 消息必须以pairshard_t, pg_t这样的类型来区分同一 OSD 上的不同 PG 分片。由于对象名到 filestore 对象的映射必须是一对一的chunk 2 与 chunk 4 的对象必须拥有不同的名字对象存储键中必须包含 chunk id。对应的核心改动在 src/common/hobject.h 中已经落地ghobject_t包含shard_id字段见 src/common/hobject.h形如tuplehobject_t, gen_t, shard_tcoll_t需要包含shard_tOSD 的 pg_map 等 PG 映射以spg_t本质上是pairpg_t, shard_t为键PG 之间的消息也需要携带shard_t对于客户端到 PG 的消息由于同一 OSD 可能同时保存同一 PG 的主分片与非主分片OSD 需要一种方式判断消息应路由到哪个分片。四、对象类Object ClassEC 池上返回 ENOTSUP对象类通常依赖本地对象数据的随机读取语义这与 EC 分片存储相冲突。文档明确对 EC 池上的对象类读操作通过发起一次特殊的同步读SYNC read来返回 ENOTSUP。也就是说EC 池不提供对象类的执行语义调用方会得到明确的不支持错误。对应到源码src/osd/ECBackend.h 提供了objects_read_sync、objects_read_local、objects_readv_sync等同步读入口供需要读回完整对象的场景使用。五、Scrub逐分片 CRC32 校验EC 池的 Scrub 不能沿用复制池的思路——把副本上存储 chunk 的 crc32 发给主 OSD 没有意义因为不同副本存的内容本身不同。由于无 overwrites 时数据只能通过追加写入ECBackend 可以在每次追加时维护每个 chunk 的 crc32。于是每个副本计算自身存储 chunk 的 crc32与本地保存的校验值比较副本只向主 OSD 报告校验是否匹配。文档同时指出一旦启用 overwritesEC 覆盖写在所有 scrub 语义讨论清楚之前所有 scrub 将被禁用相关讨论见 proposals.rst。六、CRUSH无法替换成员时保留空洞如果 CRUSH 无法为 acting set 中某个 down 掉的成员生成替换 OSDacting set 应在该位置保留空洞而不是把其余元素移出原有位置。这保证了各位置与纠删码分片的对应关系不被破坏——这与第二节中acting set 允许空洞的设计一脉相承。七、主操作概览条带切分与 W ≤ K 模型一个 RADOS put 操作可能横跨单个对象的多个条带。ECBackend 必须把应用层写入细分为逐条带的写操作若干完整条带加上最多两个部分条带。为了不失一般性文档后续只讨论单个条带整条带或部分条带的写入并用符号W表示一个条带内被写入的数据块数量即W ≤ K。处理一次 EC 条带写入共有两条数据流选择依据是写操作的大小以及所选校验生成算法的算术性质整条带写入/覆盖Whole stripe write读改写操作Read-Modify-WriteRMW。八、整条带写入Whole Stripe Write这是最简单的情况现有代码在追加写场景中已经实现主 OSD 在 RADOS 请求中收到条带的全部数据计算对应的校验块parity blocks然后把数据块与校验块发送到各自目标 shard 写入。这就是当前 EC 代码的基本形态。从源码看src/osd/ECCommon.h 中RMWPipeline::Op的requires_rmw()返回!plan.want_read——当ECTransaction::WritePlan不需要读取旧数据即整条带写入时requires_rmw()为假走的就是整条带直写路径。九、读改写Read-Modify-WriteRMW当写操作只覆盖条带的部分块W K时主 OSD 需要确定 K-W 个不被修改的块并从对应 shard 读取它们收到全部旧数据后与请求中的新数据合并计算新的校验块把修改过的块发送到各自 shard 写入确认 RADOS 操作完成。这就是 EC 覆盖写overwrite的核心成本所在一次部分写必须伴随一次远端读。RMW 的读取在源码中体现为ECCommon::RMWPipeline::Op中的pending_cache_ops与cache_ready()回调见 src/osd/ECCommon.h远端读取结果就绪后把shard_extent_map合并进remote_shard_extent_map然后推进管线状态机。十、两阶段提交Commit 与 Rollforward无论选择上述哪种算法数据写入都是两阶段过程commit提交与 rollforward前滚。主 OSD 在日志条目中描述操作及其回滚方式对应osd_types.h中的TransactionInfo::(LocalRollForward|LocalRollBack)。commit 阶段就地执行写入可能把回滚所需的信息放到一个旁写对象write-aside object中。覆盖已存在条带时回滚信息表现为一个稀疏对象sparse object其中包含被覆盖 extents 的旧值——目前通过clone_range填充本质上是一个占位实现文档明确说明在真实环境中 bluestore 将提供更高效的原子原语。rollforward 阶段当 acting set 中所有副本都提交了 commit 之后清除回滚信息。rollforward 可以延迟执行只要所有副本都已提交操作即可向客户端报告已提交。当前实现中每次发送写操作时也会指示所有先前已提交的操作进行前滚见ECBackend::try_reads_to_commit如果到达waiting_rollforward队列时管线里已没有待处理写操作就发起一次 dummy 写来推动流程前进见后文管线小节与ECBackend::try_finish_rmw。十一、ExtentCache按 extent 缓存已写数据同一对象上的写入必须能够流水线化pipeline为此 ECBackend 维护了一个由可缓存操作写入的 extent 缓存每个 extent 在被引用它的操作提交之前保持**钉住pinned**状态管线保证在读改写rmw操作运行之前不可缓存的事务如 clone 等已从管线中冲刷完毕。源码实现位于 src/osd/ECExtentCache.hECExtentCache::LRU以(offset, oid)为键维护一个受限大小的 LRU 缓存见 src/osd/ECExtentCache.hOp结构记录 reads/writes、projected_size、invalidates_cache等状态见 src/osd/ECExtentCache.h。缓存状态与并发操作何时可引用同一对象的高层不变量一一对应头文件中有详细说明。十二、Pipelinermw 与不可缓存操作互斥阅读 ExtentCache.h 能理解操作之间如何重叠。写入操作的处理涉及多个状态其中有一个 PrimaryLogPG 在上层不强制、必须由 ECBackend 自行管理的关键不变量同一对象上不可缓存操作uncacheable与读改写rmw操作不能同时运行。为简单起见ECBackend 强制执行任何包含 rmw 操作的操作都必须等待所有进行中的不可缓存操作完成。文档也注明该处未来仍有优化空间。管线状态机的具体形态在 src/osd/ECCommon.h 中RMWPipeline持有tid_to_op_mapOp 归属、oid_to_version、waiting_commit队列、completed_to/committed_to水位以及start_rmw、cache_ready、try_finish_rmw、finish_rmw等转移函数ECBackend::waiting_*队列与try_from_to_to系列函数则对应各状态的迁移路径。OSD 侧的ECBackend类定义在 src/osd/ECBackend.h其子写、子读消息处理handle_sub_write、handle_sub_read、handle_sub_read_reply、handle_sub_write_reply与submit_transaction共同构成完整的写入闭环Crimson 侧对应实现为 src/osd/ECBackendL.h 与 src/osd/ECCommonL.h。十三、关键源码索引主题参考文件设计文档本文依据doc/dev/osd_internals/erasure_coding/ecbackend.rstECBackend 类定义与消息处理src/osd/ECBackend.hCrimsonsrc/osd/ECBackendL.hRMW 管线与 Op 状态机src/osd/ECCommon.hExtentCache 与 LRUsrc/osd/ECExtentCache.h分片寻址shard_id 内嵌于对象键src/common/hobject.h主分片解析src/osd/OSDMap.hPGTemp 消息结构src/messages/MOSDPGTemp.h条带信息模型src/osd/ECUtil.hScrub 语义的 overwrites 后续讨论doc/dev/osd_internals/erasure_coding/proposals.rst十四、总结与延伸阅读ECBackend 的设计精髓可以概括为三条主线可回滚优先EC 池早期只接受 APPEND/DELETE/ATTR 等可本地回滚的操作任何写入都通过commit rollforward两阶段完成回滚信息以稀疏对象clone_range 占位保存分片位置即身份acting set 各位置与纠删码分片一一对应通过ghobject_t.shard_id、coll_t.shard_t、spg_t重构寻址允许 acting set 空洞、主分片独立指定管线化与互斥ExtentCache 钉住未提交 extent 使写操作可流水线RMW 管线强制不可缓存操作与 rmw 操作不同时运行。若要进一步深入可以继续阅读同一目录下的 developer_notes.rst、direct_reads.rst、sparse_reads.rst 与 ec_stretch_cluster.rst它们分别对应 EC 读路径优化、稀疏读与跨域扩展集群等后续演进enhancements.rst 则汇总了该领域的功能增强清单。赞分享存储分布式文件系统对象存储后端高可用【免费下载链接】cephCeph is a distributed object, block, and file storage platform项目地址https://gitcode.com/gh_mirrors/ce/ceph点击查看免费下载相关推荐Ceph EC 池稀疏读与逻辑分配保留force_allocated_extents 设计深度解析Ceph EC 池稀疏读与逻辑分配保留force_allocated_extents 设计深度解析 本文基于 Ceph 仓库中的官方设计文档 doc/dev/存储分布式文件系统对象存储后端高可用Ceph ECBackend 演进提案解析奇偶校验增量写、条带缓存与可回滚覆盖写的设计蓝图Ceph ECBackend 演进提案解析奇偶校验增量写、条带缓存与可回滚覆盖写的设计蓝图 本文以 doc/dev/osd_internals/erasure存储分布式文件系统对象存储后端高可用kinit回滚策略版本回滚与数据恢复kinit回滚策略版本回滚与数据恢复 概述 在现代化Web应用开发中版本回滚与数据恢复是保障系统稳定性的关键能力。kinit作为基于FastAPI Vu后端前端任务调度认证鉴权移动开发创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表