← Week 3: Distributed Data Structures

Day 21: Challenge — Consistent Hash Ring in Rust

Phase 1 · Jun 9, 2026

← Week 3: Distributed Data Structures

Challenge Overview

Implement a consistent hash ring with virtual nodes in Rust.

Requirements:

  1. Add/remove physical nodes, each with V virtual nodes
  2. Look up which physical node owns a given key
  3. Demonstrate that removing a node only moves K/n keys on average
  4. Write tests verifying load distribution across nodes

Stretch: add weighted nodes (some nodes get more virtual nodes than others based on capacity).

← Week 3: Distributed Data Structures

Scaffold

use std::collections::BTreeMap;

struct ConsistentHashRing {
    ring: BTreeMap<u64, String>,  // hash position → node name
    virtual_nodes: usize,
}

impl ConsistentHashRing {
    fn add_node(&mut self, name: &str) { ... }    // insert V virtual nodes
    fn remove_node(&mut self, name: &str) { ... } // remove V virtual nodes
    fn get_node(&self, key: &str) -> Option<&str> { // find successor clockwise
        let hash = self.hash(key);
        self.ring.range(hash..)
            .next()
            .or_else(|| self.ring.iter().next())
            .map(|(_, name)| name.as_str())
    }
    fn hash(&self, key: &str) -> u64 { ... } // use std::hash or SHA-1
}
← Week 3: Distributed Data Structures

Test: Measure Key Redistribution

#[test]
fn removing_node_moves_minimal_keys() {
    let mut ring = ConsistentHashRing::new(150); // 150 vnodes per node
    ring.add_node("node-a");
    ring.add_node("node-b");
    ring.add_node("node-c");

    let keys: Vec<String> = (0..10_000)
        .map(|i| format!("key-{}", i))
        .collect();

    let before: Vec<_> = keys.iter()
        .map(|k| ring.get_node(k).unwrap().to_string())
        .collect();

    ring.remove_node("node-c");

    let after: Vec<_> = keys.iter()
        .map(|k| ring.get_node(k).unwrap().to_string())
        .collect();

    let moved = before.iter().zip(after.iter())
        .filter(|(a, b)| a != b)
        .count();

    // Expect roughly 1/3 of keys to move
    assert!(moved < 4000, "Too many keys moved: {}", moved);
}
← Week 3: Distributed Data Structures

Phase 1 Recap

Week Topic Key algorithms
1 Consistency models Linearizability, CAP, PACELC, vector clocks, CRDTs
2 Consensus Paxos, Raft (election + log + snapshots), BFT, etcd/ZK
3 Data structures Bloom filter, consistent hashing, Merkle tree, LSM, skip list, DHT

Why this matters for Leo Secure Comms:

  • Certificate metadata stores → consistency model tradeoffs
  • Coordination (leader election, distributed locks) → Raft / etcd
  • Content-addressed storage → Merkle trees
  • Message routing across regions → consistent hashing

Phase 2 starts tomorrow: Async Rust — build the network services that run on these distributed foundations.