陇右九塞之间,横亘着大离王朝最浩瀚的粮仓群。三千座石窟沿三条巍峨山脉凿空而成,自北向南,绵延数百里。每一座山脉中藏着数十处险峻峡谷,峡谷崖壁上又布满深浅不一的石窟:有的洞穴阔大如校场,能纳万石青稞;有的仅是岩缝开凿的石室,只容百袋粟米。
立国之初,关隘咽喉处设立了一座高耸入云的“总簿司”。
总簿司内终日不见天日,数百名司粮文吏伏案抄录,周围堆叠着上万卷浸染防蠹药汁的厚重皮册。天下凡有漕帮车队运粮抵达,骡马队必须先在关门前排起数里长龙。押粮官捧着盖有官印的粮袋木牌,步入总簿司等候文吏翻阅卷帙。
文吏翻开泛黄的厚册,自万千洞库中逐一寻觅:哪座石窟尚有空隙?哪间暗洞适宜储粮?选定之后,文吏以朱砂大笔在主册与分册上分别勾画,再将写有“北麓、青松峡、四号窟”的引路木牌交还押粮官。运粮队这才得以扬鞭启程,跋山涉水将粮袋卸入指定石洞。
若有军前急需提粮,亦须先来总簿司翻检名册,查出昔年粮米封存何处,文吏销毁底账,方准发牌开窟。
岁月更迭,塞防渐盛,边关屯粮自数万石猛增至数千万袋。
总簿司的大案几乎要被堆积如山的账簿压垮。查验一袋粟米的入库归属,往往要翻阅数十本残破卷宗,长桌前咳喘连连,文吏们从拂晓忙到深夜,关门外的车马队却依旧排到了群山之外。夏日暑气蒸腾,粮袋在关外暴晒发霉;冬日暴雪封峡,车马在冰雪中受冻倒毙。
更可怕的是火烛与墨误。
一次雷火引燃了总簿司偏殿,千卷账册化作飞灰,数万名将士守在关前,空对莽莽千山,竟无人知晓哪座石窟藏着何种军粮,形同坐拥宝山而活活饿毙。又有文吏疲倦昏聩,誊写失准,将同批送达的三份备用粮,糊里糊涂全分派进了同一道受地脉湿气浸润的狭窄岩溶洞中;次年山洪暴发,泥石流倾泻而下,该批粮米竟被一锅端灭,未留半点生机。
边关粮政濒临瓦解之际,一位隐居终南山的历法兼机关名宿裴先生受诏出山。
裴先生踏入喧嚣漫天的总簿司,既未增添文吏,亦未研磨朱墨。他环视满殿堆砌如山的账册,拂袖一笑:“天下粮粟浩如星海,以有涯之纸笔追逐无涯之存纳,安能不竭?何须向凡夫求问粮藏何处?千峰万壑之规整,早已铭刻在造化神机之中。”
言毕,裴先生传令撤去总簿司所有案牍文吏,将累朝积攒的数万卷皮册尽数封入库底,一概弃置不用。
他取出一面以精铜铸造的浑天星盘。星盘圆周层层相扣,刻度严密精密。
裴先生召集三千石窟的仓正与各路押运掌柜,当众公布了三道法门:
第一,山川之谱(拓扑金匮)。他将九塞三千石窟的脉络化作一张金箔树图:最高为“秦岭、祁连、贺兰”三大山脉,次级为诸条深峡,再下为各处营盘,最底层为具体石窟。石窟各有分量:万石大窟刻重木楔,百石小洞填轻铜片,轻重规制分明,天下仓官人手临摹一卷。
第二,分形之规(隔离律令)。凡入塞粮米,必存三份,以备不虞。但这三份绝非随意堆放,星盘内嵌死规矩:“三袋同根粮,首份落东山,次份进西脉,末份走中壑;且不可共处同一山峡、不得共受同一水源。”
第三,九宫运算法(算力代簿)。没有文吏,没有台账,没有查询。
每袋军粮自出产之时,麻布上便烙有独一无二的织造密号与批次朱印。押粮官抵达关口,不必通报任何人,只需掏出随身所携的铜盘,将粮袋印号拨入星盘的机括天心,再依序扳动齿轮三遭。
机芯咬合,指针飞旋。铜盘内部以天地阴阳算术(伪随机离散推衍)急速运转,依据粮袋密号与各窟轻重权重,自顶层山脉逐级往下推演:
指针轻震,落入首环:“南山祁连”; 复转次环,定于“雪枫峡”; 再越诸小洞,以千斤大窟权重之势,稳稳咬定“七号玄武巨窟”。
若欲寻第二处备用窟,只需按隔离律令转动机括旁侧副榫,指针立刻避开南山,在北麓贺兰山的断谷深处指明另一座石室。
整套推演,不过弹指三息之间。押粮官拨完铜盘,跨上骏马,直奔指针所示的石窟卸粮而去。
当军前主将需提调粮草时,军令官同样取粮袋编号拨盘,指针分毫不差指向当年卸粮的同一座石窟,开锁启封,粮米赫然在目。
千里群山之间,再无一座排队的关门,再无一本翻烂的名册。
数年后,祁连山深处的一座古窟因地动崩塌。守关将军大惊失色,急问是否需重新测算天下数千万袋存粮的归属。
裴先生神色自若,只命仓官向各关塞颁发了一枚薄如蝉翼的修补铜齿,嵌于星盘中将崩塌石窟的权重抹为平地。
奇迹发生了:依照星盘新齿推演,天下原本安睡在其余两千余座石窟中的数千万袋粮米,纹丝不动;唯独原本算向塌陷废窟的那一小部分粮袋,在指针下平滑散落至同峡谷内尚有余力的邻近各窟之中。
无一卷册籍,而万石井然;无一名文吏,而关防不乱。九宫星盘悬于辕门之上,千峰万壑化作天然棋局。
——到这儿你大概已经认出来了:这就是现代分布式存储基石——Ceph 核心数据分布算法 CRUSH(Controlled Replication Under Scalable Hashing,可控扩展哈希复制算法)。
这是什么
在海量分布式存储系统(如 PB/EB 级对象与块存储)中,如何决定一个数据对象(Object)究竟存放在哪台机器、哪个磁盘上,是系统架构的核心命题。
传统的分布式存储方案往往依赖集中式元数据目录(如元数据服务器 Metadata Server 或查表寻址):每写入一个文件,中心节点便记录一条 对象ID → 节点IP/磁盘ID 的映射关系。然而当对象数量达到百亿、千亿规模时,元数据中心不可避免地会遭遇内存耗尽、磁盘 I/O 瓶颈、网络拥塞以及单点故障的死局。
2006 年,Sage Weil 在其博士论文中提出了 CRUSH 算法,彻底终结了“查表存取”的时代:
- 计算代替查表($O(1)$ 寻址):客户端写入或读取数据时,无需向任何中央节点索取存放位置,而是直接在本地运行 CRUSH 算法。算法输入仅需三样东西:对象标识符($x$)、集群拓扑映射表(Cluster Map) 与 放置规则(Placement Rule)。通过伪随机确定性哈希函数,客户端能在纳秒级时间内直接计算出存放该对象的存储守护进程列表($\vec{OSD} = (osd_1, osd_2, \dots, osd_n)$),实现了完全去中心化的百万级并发寻址。
- 感知故障域的层级拓扑(Hierarchical Cluster Map):CRUSH 将整个机房的硬件物理布局抽象为一棵树形拓扑图(如
Root → Datacenter → Rack → Row → Host → OSD)。管理员可以编写 placement rule(例如:三副本必须跨三个不同的机架,或跨不同的可用区供电单元)。CRUSH 在沿拓扑树自顶向下递归选点时,会严格遵循故障隔离约束,从根源上杜绝由于单机柜断电或单交换机故障而导致的数据丢失。 - 权衡容量的桶算法(Bucket Types):CRUSH 拓扑中的内部节点被称为“桶”(Bucket)。为了应对异构存储介质(如大容量机械盘与高速固态盘并存)以及不同拓扑层级的变更频率,CRUSH 提供了多种不同计算复杂度与重平衡特性的桶算法:
- Uniform:所有子节点权重完全一致,寻址极快($O(1)$),但无法增减不同规格设备。
- List:类似链表,将新设备追加在表头,扩容时历史数据绝不迁移,但寻址开销随深度呈 $O(n)$ 增长。
- Tree:将子节点组织为二叉树,寻址复杂度为 $O(\log n)$,适合规模极大的固定集群。
- Straw / Straw2:现代 Ceph 的默认选择。让所有子节点像插在签筒中的吸管一样,根据各自的权重动态竞争。当某个磁盘被剔除或扩容时,仅在该磁盘与相关节点间发生最小化的必要数据搬迁,其余完全无关磁盘上的海量数据纹丝不动。
为什么重要
CRUSH 是分布式存储领域从“单点集中协调”迈向“全分布式自组织”的划时代发明:
- 突破存储规模天花板:消除了元数据查寻瓶颈后,Ceph 能够横向扩展至成千上万个存储节点(OSD)和数万亿个对象,集群整体性能随磁盘与客户端数量增加而线性提升。
- 极致的容灾可靠性:通过将机柜、电源、PDU、可用区等物理故障边界固化在算法规则中,系统在遭遇机房级断电、机架冒烟或光纤被挖断时,仍能数学性地保证至少有一个健康副本存活于隔离的安全区域。
- 平滑扩容与最小化重平衡(Minimal Data Movement):传统模哈希($hash(key) \pmod N$)在节点增减时会导致全集群几乎 $100\%$ 的数据重新洗牌,引发集群网络雪崩与磁盘 I/O 瘫痪。而 CRUSH(尤其是 Straw2 算法)在新增一台服务器时,只会均匀地从现有节点中“抽取”刚好等于新增容量比例的数据迁入新盘,整个集群在扩容期间依然保持高可用业务读写。
- 架构权衡与工程坑点:
- PG(Placement Group)数量规划:对象并非直接映射到 OSD,而是先映射到逻辑归宿 PG,再由 CRUSH 将 PG 映射至 OSD。若 PG 总数规划过小,会导致严重的数据倾斜(某些磁盘爆满而其余磁盘闲置);若 PG 总数过大,则会耗尽 OSD 守护进程的内存与 CPU。
- CRUSH Map 变更的抖动:虽然 Straw2 实现了最小迁移,但在大规模生产集群中修改 CRUSH 规则(如改变副本跨机架策略)仍会触发海量跨机柜网络同步(Peering & Backfill),必须通过
ceph osd set-max-backfills等限流手段严密受控执行。
隐喻对应表
- 陇右群山的三千座石窟与深浅岩洞 → 分布式存储集群中的多台物理服务器与磁盘(OSDs)
- 堆满账册、人满为患且易遭火灾的总簿司 → 传统的集中式元数据服务器与查表寻址(Centralized Metadata Server / Lookup Directory)
- 裴先生铸造的九宫浑天星盘 → 客户端本地运行的 CRUSH 算法引擎(CRUSH Algorithm)
- 山川之谱(山脉→峡谷→洞窟的树形金箔) → 描述硬件拓扑层级的集群映射图(Hierarchical Cluster Map)
- 分形之规(三份粮必跨山越峡且不得同受一水) → 故障域隔离放置规则(Placement Rule & Failure Domain Isolation)
- 依据粮袋布面上独一无二的织造密号拨盘 → 输入对象标识符(Object ID $x$)与哈希计算
- 依洞窟容积装配不同轻重铜片的机括 → 基于权重的桶算法(Bucket Algorithms: Straw2 & Weights)
- 无需通报文吏、拨盘即知石窟归宿 → 客户端无中央协调的本地自主寻址(Algorithmic Self-Routing / Decentralized Placement)
- 单窟崩塌换上修补齿、其余诸窟粮米绝不妄动 → 节点宕机/扩容时的最小化数据迁移与自愈重平衡(Minimal Data Movement & Rebalancing)
Between the nine fortified passes of the Longyou frontier lay the grandest granary complex of the Great Li Dynasty. Three thousand stone caves had been chiseled into three soaring mountain ranges, stretching for hundreds of leagues from north to south. Within each range wound dozens of rugged valleys, and upon the cliff faces stood caverns of vastly different capacities: some were as cavernous as military parade grounds, capable of sheltering ten thousand bushels of barley; others were modest clefts carved into the rock, holding merely a hundred sacks of millet.
In the early days of the empire, a towering fortress known as the “Grand Registry Bureau” stood sentinel at the gateway pass.
Within the bureau, sunlight never penetrated. Hundreds of grain scribes hunched over cedar tables, surrounded by tens of thousands of vellum ledgers treated with herb-infused insect repellent. Whenever a grain caravan arrived from the central plains, pack horses and ox carts backed up for leagues outside the fortress gates. The transport officer had to present wooden tokens bearing imperial stamps and wait in endless lines while scribes scoured their voluminous records.
A scribe would leaf through yellowed pages, seeking among thousands of caves: which cavern had vacant space? Which dark recess suited dry grain? Once decided, the scribe dipped his brush in cinnabar, marked both the master ledger and branch volumes, and handed the officer a wooden guide-token inscribed with “North Range, Pine Valley, Cavern No. 4.” Only then could the caravan snap its whips and journey across peaks and ravines to unload its cargo.
When armies on the march needed provisions, requisitions likewise had to pass through the Grand Registry to uncover where grain had been sealed years prior, cancel the records, and grant tokens to unseal the caves.
As the decades slipped by and border garrisons expanded, the stockpiled grain exploded from tens of thousands of bushels to tens of millions of sacks.
The long tables of the Grand Registry groaned under the weight of rotting parchment. Locating a single sack of grain often demanded sifting through dozens of tattered scrolls amidst endless coughing and sighs. Scribes labored from dawn to midnight, yet caravans outside the mountain pass still queued far beyond the horizon. In summer heat, grain sacks spoiled under the relentless sun; in winter blizzards, pack animals froze in their tracks.
Worse still were fire and ink-borne errors.
One night, lightning struck the bureau’s eastern wing, reducing thousands of ledgers to ash. Tens of thousands of garrison troops stood before the mountains, looking out across three thousand caves, yet no living soul knew which cavern held what provisions—they were starving atop a mountain of buried gold. On other occasions, exhausted scribes blundered, assigning all three redundant backup sacks of a vital shipment to the very same damp, low-lying limestone cavern. When spring floods triggered a mudslide, the entire shipment was wiped out in a single stroke, leaving no reserve alive.
As border logistics teetered on the brink of collapse, Master Pei, an astronomer and master horologist living in reclusion on Mount Zhongnan, answered an imperial summons.
Master Pei entered the chaotic halls of the Grand Registry. He neither drafted new scribes nor ground fresh ink. Surveying the mountains of parchment, he swept his sleeves and chuckled: “The grain of the realm is as vast as the stars. To chase an infinite harvest with finite ink and paper—how could it not exhaust you? Why ask mortal scribes where grain resides? The order of three thousand peaks is already written into the architecture of heaven and earth.”
With that, Master Pei ordered every ledger closed and sealed into deep vaults, discarded forever.
From his wooden trunk, he produced a bronze armillary astrolabe. Its concentric rings were finely engraved with interlocking teeth and hair-thin scales.
Gathering the grain wardens and caravan masters, Master Pei unveiled three cardinal laws:
First, The Chart of Peaks and Valleys (Hierarchical Topology). He mapped the three thousand caverns into a golden tree diagram: at the summit stood the three great mountain ranges—Qinling, Qilian, and Helan; beneath them branched the deep valleys; below the valleys sat the fortress camps; and at the foundation lay the individual caverns. Each cave possessed a measured weight: a grand hall holding ten thousand bushels received a heavy oak block, while a narrow crevice received a feather-light bronze slip. Every warden received a replica of this chart.
Second, The Mandate of Separation (Failure Domain Isolation). Every grain deposit required three replicas against disaster. But these three copies were never placed at whim; the astrolabe held an unbending decree: “Of three sibling sacks, the first shall enter the Eastern Range, the second shall cross to the Western Peaks, and the third shall rest in the Central Valley. Never shall two share the same gorge, and never shall two drink from the same stream.”
Third, The Nine-Palace Computation (Computing in Place of Lookups). No scribes. No ledgers. No central queries.
When grain was bagged, an indelible seal was branded upon the hemp cloth—a unique weave number and imperial serial. When a caravan reached the mountain pass, the driver consulted no official. He drew his personal bronze astrolabe, dialed the sack’s serial number into the central spindle, and turned the bronze crank three full revolutions.
Cogs meshed; brass gears hummed. The astrolabe’s internal clockwork executed a deterministic pseudo-random progression, walking down the hierarchy of peaks and caverns according to the sack’s number and the proportional weights of the caves:
The needle clicked and settled upon the outer ring: “Southern Qilian Range”; The second ring aligned to “Snow Maple Valley”; Sweeping past minor crags, drawn by the gravitational pull of the largest cavern’s weight, it snapped firmly into “Cavern No. 7, The Black Tortoise.”
To place the second replica, the driver simply notched the auxiliary lever dictated by the Mandate of Separation. The gears instantly steered clear of the southern mountains, pointing deterministically to a secluded cave in the northern Helan Range.
The entire derivation took no more than three breaths. The driver packed his astrolabe, leaped onto his horse, and rode directly to the designated cave to deliver his grain.
When military commanders needed to retrieve provisions, their quartermasters dialed the exact same serial number into their own astrolabes. The needle halted unerringly at the exact same stone chamber where the grain had been stowed seasons before.
Across thousands of peaks, queues vanished from the gates. Worn ledgers were forgotten.
Years later, an earthquake collapsed an ancient cavern deep within the Qilian Mountains. The garrison general panicked, fearing that tens of millions of records would need to be recalculated across the empire.
Master Pei remained serene. He dispatched a wafer-thin brass shim to the border posts, slipping it into the astrolabes to flatten the collapsed cave’s weight to zero.
A marvel occurred: under the updated gear ratio, tens of millions of sacks resting peacefully in the other thousands of caves remained completely untouched. Only the tiny fraction of grain originally calculated for the collapsed cavern was gently redistributed among neighboring caves in the same valley with capacity to spare.
Without a single page of text, myriad bushels lay in perfect harmony; without a single scribe, the frontier stood secure. The Nine-Palace Astrolabe hung above the gates, and a thousand peaks became a self-navigating chessboard.
——By now you have probably recognized it: this is the foundation of modern distributed storage—Ceph’s core data distribution algorithm, CRUSH (Controlled Replication Under Scalable Hashing).
What it is
In massive distributed storage systems spanning petabytes or exabytes across tens of thousands of hard drives, deciding where an object should live is the core architectural challenge.
Traditional distributed storage relied on centralized metadata tables (such as a Metadata Server or lookup directory): every time a file was written, a central catalog recorded an explicit mapping of ObjectID → NodeIP/DiskID. But as the number of objects surged into billions and trillions, central metadata servers inevitably hit hard limits: memory exhaustion, disk I/O bottlenecks, network saturation, and catastrophic single-point failures.
In 2006, Sage Weil introduced the CRUSH algorithm in his seminal doctoral thesis, forever ending the era of table lookups:
- Computation over Lookup ($O(1)$ Addressing): When reading or writing data, clients never query a central authority for placement coordinates. Instead, they execute the CRUSH algorithm locally. The algorithm requires only three inputs: the Object Identifier ($x$), the Hierarchical Cluster Map ($M$), and the Placement Rule ($R$). Using deterministic pseudo-random hash functions, the client calculates the exact list of target storage daemons ($\vec{OSD} = (osd_1, osd_2, \dots, osd_n)$) in nanoseconds, enabling entirely decentralized, massively parallel data access.
- Failure-Domain-Aware Hierarchical Topology: CRUSH models the physical layout of a data center as a tree (
Root → Datacenter → Rack → Row → Host → OSD). Administrators configure placement rules (for instance: place three replicas across three separate racks, or across different power distribution zones). As CRUSH traverses the tree top-down, it strictly enforces these fault-isolation constraints, ensuring that a severed network cable, power supply blowout, or rack failure cannot take down all replicas simultaneously. - Capacity-Weighted Bucket Algorithms: Internal nodes within the CRUSH hierarchy are known as “buckets.” To accommodate heterogeneous hardware (mixing high-capacity spinning disks with ultra-fast NVMe SSDs) and different rates of hardware churn, CRUSH provides several bucket types with distinct computational complexities and rebalancing characteristics:
- Uniform: All child nodes have identical weights. Selection is $O(1)$, but adding or removing devices of varying capacities is impossible.
- List: Children are linked sequentially. Adding a new device appends it to the head, guaranteeing zero data movement among existing devices, but traversal cost scales as $O(n)$.
- Tree: Children are organized into a binary tree with $O(\log n)$ traversal time, well-suited for very large, stable clusters.
- Straw / Straw2: The modern default in Ceph. All children compete dynamically based on their individual weights, like drawing straws from a canister. When an OSD fails or a new disk is introduced, data migration occurs strictly between the altered device and its immediate peers; data across unaffected disks remains completely undisturbed.
Why it matters
CRUSH was a paradigm shift in distributed storage, transforming systems from centrally coordinated clusters into self-organizing fleets:
- Shattering the Scale Ceiling: By removing centralized lookup tables, Ceph scales horizontally to thousands of storage nodes (OSDs) and trillions of objects. Throughput scales linearly with the addition of storage drives and client nodes.
- Resilient Fault Isolation: By embedding physical failure boundaries (power feeds, racks, failure domains, availability zones) directly into algorithmic rules, the system mathematically guarantees that data survives even when entire server racks go dark.
- Smooth Expansion with Minimal Data Movement: Under classic modulo hashing ($hash(key) \pmod N$), adding or removing a node rehashes nearly $100\%$ of all keys across the cluster, triggering disastrous network floods and storage paralysis. CRUSH (especially Straw2) ensures that adding an $n$-th drive migrates only a minimal $1/n$ fraction of data, allowing live production clusters to expand seamlessly under heavy workloads.
- Architectural Pitfalls to Avoid:
- PG (Placement Group) Sizing: Objects map first to logical Placement Groups (PGs), which CRUSH then maps to OSDs. If the PG count is too low, data distribution skews severely, leaving some disks overflowing while others sit idle. If the PG count is too high, OSD daemons suffer excessive memory and CPU overhead.
- CRUSH Map Transition Shock: While Straw2 minimizes rebalancing, sweeping alterations to CRUSH rules (such as migrating from host-level to rack-level replication) will trigger immense data shuffling (peering and backfilling). Production operators must strictly throttle recovery bandwidth using parameters like
ceph osd set-max-backfillsto prevent user latency spikes.
Metaphor mapping
- Three thousand caverns across the Longyou mountains → Storage daemons and physical disks in a cluster (OSDs)
- The overcrowded, bottlenecked Grand Registry Bureau → Traditional centralized metadata servers and lookup tables (Metadata Server / Central Catalog)
- Master Pei’s Nine-Palace Armillary Astrolabe → The locally computed CRUSH algorithm engine (CRUSH Algorithm)
- The Chart of Peaks and Valleys on golden foil → The hierarchical cluster map (Hierarchical Cluster Map)
- The Mandate of Separation across ranges and rivers → Failure domain placement rules (Placement Rules & Failure Domain Isolation)
- Dialing the unique weave serial number into the central gear → Hashing the Object ID ($x$) to determine placement
- Calibrating cave weights with oak and bronze blocks → Capacity-weighted bucket types (Straw2 Bucket Weights)
- Bypassing the bureau to deliver grain directly to the indicated cave → Completely decentralized, client-side $O(1)$ routing (Algorithmic Self-Routing)
- Inserting a brass shim to nullify a collapsed cave while other grain rests untouched → Minimal data movement during node failure or expansion (Minimal Data Movement & Rebalancing)