Apache ZooKeeper is a centralized, fault-tolerant service for maintaining configuration information, naming, distributed synchronization, and group services in distributed systems.
Installation and Setup
ZooKeeper binaries can be downloaded from the official Apache releases page. After extraction, configure zoo.cfg in the conf/ directory. A minimal three-node ensemble example:
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/var/lib/zookeeper
clientPort=2181
server.1=192.168.30.88:2888:3888
server.2=192.168.30.89:2888:3888
server.3=192.168.30.90:2888:3888:observer
Start each instance with bin/zkServer.sh start and verify status using bin/zkServer.sh status.
Node Lifecycle and Roles
ZooKeeper servers operate in one of four runtime roles:
- LOOKING: Node is participating in leader election.
- FOLLOWING: Follower replicates state from the leader and votes during elections.
- OBSERVING: Observer mirrors leader state but does not vote—ideal for read-heavy workloads.
- LEADING: The elected node handles client write requests and coordinates state propagation.
To designate a server as an observer, append :observer to its server.x entry (as shown above) and ensure peerType=observer appears only in that node’s zoo.cfg.
ZNode Types and Semantics
ZooKeeper organizes data in a hierarchical tree of znodes, each supporting distinct persistence and ordering behaviors:
- Persistent: Survives session termination; manually removed only.
- Ephemeral: Bound to client session lifetime; auto-deleted on disconnect. Cannot host children.
- Sequential: Appends a monotonically increasnig counter to the node name (e.g.,
/task-0000000001). Can be combined with persistent or ephemeral. - Container: Automatically deleted when it has no children—triggered lazily by the server during periodic cleanup.
- TTL (Time-to-Live): Persistent nodes may be assigned a millisecond-based TTL. Requires
extendedTypesEnable=trueinzoo.cfg; deletion occurs asynchronously after expiry.
Command-Line Operations
Use zkCli.sh to interact directly with a running ensemble:
# Connect to local instance
./zkCli.sh -server localhost:2181
# List root children
ls /
# Create persistent sequential node with data
create -s /tasks "initial-task"
# Create ephemeral node
create -e /workers/worker-1 "host-88"
# Read node content and metadata
get -s /tasks
# Watch for child changes (one-time trigger)
ls -w /
# Delete with version check (optimistic concurrency)
delete -v 1 /tasks0000000001
# Recursive deletion
deleteall /tasks
# Set new data with version enforcement
set -v 2 /tasks "updated-task"
Java Integration Using Apache Curator
Curator simplifies ZooKeeper client development. Add the dependency:
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.6.0</version>
</dependency>
Example: retrieve and print all immediate chilrden of the root path:
public class ZkChildReader {
public static void main(String[] args) throws Exception {
RetryPolicy policy = new ExponentialBackoffRetry(1000, 3);
try (CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString("192.168.30.88:2181")
.retryPolicy(policy)
.build()) {
client.start();
List<String> children = client.getChildren().forPath("/");
children.forEach(System.out::println);
}
}
}
GUI Tools for Management
For visual inspection and debugging, tools like PrettyZoo provide intuitive browsing of znode hierarchies, ACLs, and watches. It connects over standard ZooKeeper client ports and supports authentication and TLS.