Mastering ZooKeeper: 7 Real-World Use Cases and Code Samples

ZooKeeper is an open‑source distributed coordination service that provides a simple, efficient mechanism for managing shared state, and this guide explores seven typical scenarios—including distributed locks, service registration, configuration management, queues, leader election, notifications, and barriers—complete with Java code examples and usage details.

Xuanwu Backend Tech Stack
Xuanwu Backend Tech Stack
Xuanwu Backend Tech Stack
Mastering ZooKeeper: 7 Real-World Use Cases and Code Samples

ZooKeeper is an open‑source distributed coordination service framework that offers a simple and efficient mechanism to manage shared state in distributed systems. It implements a distributed tree‑like data structure, similar to a file system, focused on storing small amounts of metadata and status information.

Typical Application Scenarios

1. Distributed Lock

In a distributed system, multiple processes may need mutually exclusive access to a shared resource. ZooKeeper can implement a distributed lock by creating an ephemeral node.

public class ZKDistributedLock {
    private ZooKeeper zk;
    private String lockPath = "/distributed_lock";

    public boolean acquireLock() {
        try {
            // Create an ephemeral node to attempt lock acquisition
            zk.create(lockPath, "lock".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
            return true; // Lock acquired
        } catch (KeeperException.NodeExistsException e) {
            // Node already exists, lock held by another client
            return false;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void releaseLock() {
        try {
            zk.delete(lockPath, -1);
        } catch (Exception e) {
            // Handle exception
        }
    }
}

When a client disconnects or crashes, the temporary node is automatically deleted, releasing the lock and preventing deadlocks.

2. Service Registration and Discovery

Service providers register their information (e.g., IP address, port) in ZooKeeper at startup, and service consumers discover available services through ZooKeeper.

// Service provider registers itself
String servicePath = "/services/userService";
String serviceData = "192.168.1.100:8080";
zk.create(servicePath, serviceData.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);

// Service consumer discovers services
List<String> services = zk.getChildren("/services", true);
for (String service : services) {
    byte[] data = zk.getData("/services/" + service, false, null);
    String serviceInfo = new String(data);
    // Use serviceInfo to connect to the service
}

When a provider goes offline, its temporary node is automatically removed, and consumers can detect the change via ZooKeeper's watch mechanism.

3. Configuration Center

ZooKeeper can serve as a configuration center, centrally managing configuration data for distributed systems. Applications can watch configuration nodes for changes and obtain the latest settings in real time.

// Create a configuration node
zk.create("/config/database", "jdbc:mysql://localhost:3306/mydb".getBytes(),
          ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

// Watch for configuration changes
zk.getData("/config/database", event -> {
    if (event.getType() == EventType.NodeDataChanged) {
        byte[] newData = zk.getData("/config/database", true, null);
        updateDatabaseConfig(new String(newData));
    }
}, null);

This approach enables dynamic configuration updates without restarting applications.

4. Distributed Queue

ZooKeeper can implement a distributed queue for task distribution and processing.

// Producer: create sequential node
String taskPath = zk.create("/tasks/task-", taskData.getBytes(),
                           ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);

// Consumer: fetch and process tasks
List<String> tasks = zk.getChildren("/tasks", false);
Collections.sort(tasks); // Order by sequence number
for (String task : tasks) {
    byte[] data = zk.getData("/tasks/" + task, false, null);
    processTask(data);
    zk.delete("/tasks/" + task, -1);
}

5. Leader Election (Cluster Election)

In a master‑slave architecture, ZooKeeper can be used to elect a single master node, ensuring only one active master in the cluster.

// Attempt to become master
String masterPath = "/master";
try {
    zk.create(masterPath, serverId.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    becomeMaster(); // Successfully created node, now master
} catch (KeeperException.NodeExistsException e) {
    // Master already exists, set a watch to be notified when it disappears
    zk.exists(masterPath, event -> {
        if (event.getType() == EventType.NodeDeleted) {
            tryBecomeMaster();
        }
    });
}

If the master node fails, other nodes detect the deletion via the watch and trigger a new election.

6. Distributed Notification / Coordination

ZooKeeper's watch mechanism can be used to implement notifications and coordination across distributed components.

// Watch for a signal node
zk.exists("/signal", event -> {
    if (event.getType() == EventType.NodeCreated) {
        doSomething(); // React to the signal
    }
});

// Send a notification
zk.create("/signal", "start".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

7. Distributed Barrier

ZooKeeper can implement a barrier to synchronize multiple processes in a distributed system.

// Create a barrier node
String barrierPath = "/barrier/phase1";
zk.create(barrierPath, "ready".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

// Each participant registers itself
String participantPath = barrierPath + "/participant-" + id;
zk.create(participantPath, "ready".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);

// Wait until the required number of participants have joined
while (true) {
    List<String> participants = zk.getChildren(barrierPath, false);
    if (participants.size() >= threshold) {
        break; // Barrier satisfied, proceed
    }
    Thread.sleep(1000); // Retry after a short pause
}
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Javaservice discoveryConfiguration ManagementZooKeeperdistributed lockDistributed Coordinationleader election
Xuanwu Backend Tech Stack
Written by

Xuanwu Backend Tech Stack

Primarily covers fundamental Java concepts, mainstream frameworks, deep dives into underlying principles, and JVM internals.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.