按权重和故障域计算数据放置
Ceph 的 CRUSH 使用拓扑、权重与规则,为数据放置计算候选设备集合。
相关概念
工程问题#
分布式存储需要将副本或纠删码分片分散到不同故障域,并适应设备容量差异与集群成员变化。
实际实现#
CRUSH map 描述 OSD、主机和机架等层级,规则约束从哪些桶中选择、在哪个故障域分离。相同输入和映射可以得到确定的放置结果。
处理流程#
- 读取共享的 CRUSH map 与规则
- 按输入沿拓扑层级做加权选择
- 满足故障域与设备约束
- 获得目标设备集合
源码片段#
固定版本 · 原文摘录src/crush/mapper.cv19.2.0 · L346–L365
346 unsigned int i, high = 0;347 __s64 draw, high_draw = 0;348 __u32 *weights = get_choose_arg_weights(bucket, arg, position);349 __s32 *ids = get_choose_arg_ids(bucket, arg);350 for (i = 0; i < bucket->h.size; i++) {351 dprintk("weight 0x%x item %d\n", weights[i], ids[i]);352 if (weights[i]) {353 draw = generate_exponential_distribution(bucket->h.hash, x, ids[i], r, weights[i]);354 } else {355 draw = S64_MIN;356 }357358 if (i == 0 || draw > high_draw) {359 high = i;360 high_draw = draw;361 }362 }363364 return bucket->h.items[high];365}bucket_straw2_choose
这里是 straw2 桶的一次选择:遍历桶内条目,用输入、条目 ID、轮次和权重生成确定的 draw,取最大值。它展示加权选择的实现;故障域遍历、重试与副本去重在外层规则执行中,不能把这段循环当作完整 CRUSH。
收益与取舍#
工程分析带来的收益
- 无需逐对象维护完整中心化位置表
- 把故障域与容量权重写入放置规则
付出的代价
- 工程分析:拓扑或权重变化会触发重映射
- 放置结果仍需结合集群状态处理故障与恢复
可比较的选择
普通一致性哈希环结构较简单,但层级故障域和复杂放置规则需要另行设计。
版本与适用范围#
依据 Ceph Squid 文档及 v19.2.0 实现。片段展示 straw2 桶内加权选择;完整放置还包含 CRUSH 规则遍历、故障域约束及对象到 PG、OSDMap 等环节,其他桶算法另有实现。