ZooKeeper: The Coordinator

Distributed systems are like a room full of people shouting. Without a moderator, you get chaos. Apache ZooKeeper is that moderator. It is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and group services.

[!TIP] Why not just use a Database? Databases are designed for Throughput and Storage. ZooKeeper is designed for Latency and Ordering. It keeps the entire data tree in RAM for speed and guarantees FIFO ordering of updates.


1. The Data Model: ZNodes

ZooKeeper looks like a standard Linux file system, but optimized for coordination.

  • Root: /
  • Nodes: /app, /app/config.
  • Data: Each node stores tiny amounts of data (<1MB).

Node Types (The “Mode”)

  1. Persistent: Stays forever. (e.g., /db-config).
  2. Ephemeral: Dies when the client disconnects. (e.g., /active-users/user-1). Crucial for Failure Detection.
  3. Sequential: Appends a number. (e.g., /queue/task-001). Crucial for Ordering.

2. The Superpower: Watches

Polling (“Is it ready yet?”) kills performance. ZooKeeper uses Watches (Push notifications).

  1. Client: “Watch /config.”
  2. ZooKeeper: “Acknowledged.”
  3. Admin updates /config.
  4. ZooKeeper → Client: “EVENT: NodeDataChanged”.

ZAB Atomic Broadcast Diagram

Leader
Follower
Client
1. Write Request
2. PROPOSAL (Zxid)
3. ACK
4. COMMIT

3. Interactive Demo: The Service Registry

Cyberpunk Mode: Visualize Service Discovery.

  • Role: You are the Load Balancer.
  • Task: Route traffic to active workers.
  • Mechanism: Watch the /workers directory.

Instructions:

  1. Start Worker: Spawns a new Ephemeral Node. Watch the Load Balancer update instantly.
  2. Kill Worker: Simulates a crash. The Ephemeral Node vanishes. The Load Balancer removes it from the routing table.
ZooKeeper Data Tree (RAM)
📂 /
📂 workers (Persistent)
(empty)
Load Balancer (Client)
State: Connected
Watching: /workers
Routing Table:
  • (No Upstreams)
System Ready.

4. The Curator Framework

Writing raw ZooKeeper code is painful. Dealing with connection drops, retries, and edge cases is hard. Netflix created Curator to solve this.

Recipe: Distributed Lock

// Connect to ZK
CuratorFramework client = CuratorFrameworkFactory.newClient("localhost:2181", new ExponentialBackoffRetry(1000, 3));
client.start();

// The "Recipe" handles all logic (creating ephemeral nodes, watching, retrying)
InterProcessMutex lock = new InterProcessMutex(client, "/my-distributed-lock");

try {
    if (lock.acquire(10, TimeUnit.SECONDS)) {
        try {
            // Critical Section: Access Shared Resource
            doWork();
        } finally {
            lock.release();
        }
    }
} catch (Exception e) {
    // Handle failure
}

Recipe: Leader Election

LeaderSelector listener = new LeaderSelector(client, "/master-election", new LeaderSelectorListenerAdapter() {
    public void takeLeadership(CuratorFramework client) throws Exception {
        // You are now the Leader!
        // Do work here...
        // If this method exits, you give up leadership.
    }
});
listener.autoRequeue();
listener.start();

5. ZAB vs The World

ZooKeeper uses ZAB (ZooKeeper Atomic Broadcast).

  • Ordered: Guarantees FIFO ordering of updates.
  • Primary-Backup: Unlike Raft (Peer-to-Peer), ZK is optimized for read-heavy workloads where followers serve reads.

Summary

  • ZNodes: The building blocks. Ephemeral nodes are the heartbeat of the system.
  • Watches: The nervous system. Enables real-time reaction to cluster changes.
  • Curator: The shield. Use it instead of raw ZK libraries.