Ceph/RADOS / CRUSH

按权重和故障域计算数据放置

Ceph 的 CRUSH 使用拓扑、权重与规则,为数据放置计算候选设备集合。

v19.2.0存储与数据放置核验 2026-10-08
相关概念

工程问题#

分布式存储需要将副本或纠删码分片分散到不同故障域,并适应设备容量差异与集群成员变化。

实际实现#

CRUSH map 描述 OSD、主机和机架等层级,规则约束从哪些桶中选择、在哪个故障域分离。相同输入和映射可以得到确定的放置结果。

处理流程#

  1. 读取共享的 CRUSH map 与规则
  2. 按输入沿拓扑层级做加权选择
  3. 满足故障域与设备约束
  4. 获得目标设备集合

源码片段#

固定版本 · 原文摘录
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 等环节,其他桶算法另有实现。

参考来源#

源码、官方文档与原始论文
01
Ceph · CRUSH Maps

rados/operations/crush-map · CRUSH Maps / CRUSH Rules

官方文档Squid
4 个匹配案例