SlideShare a Scribd company logo
Copyright © 2008 The Apache Software Foundation. All rights reserved.
Programming with ZooKeeper - A basic
tutorial
by
Table of contents
1 Introduction........................................................................................................................ 2
2 Barriers............................................................................................................................... 3
3 Producer-Consumer Queues...............................................................................................5
4 Complete Source Listing....................................................................................................7
Programming with ZooKeeper - A basic tutorial
Page 2Copyright © 2008 The Apache Software Foundation. All rights reserved.
1 Introduction
In this tutorial, we show simple implementations of barriers and producer-consumer queues
using ZooKeeper. We call the respective classes Barrier and Queue. These examples assume
that you have at least one ZooKeeper server running.
Both primitives use the following common excerpt of code:
static ZooKeeper zk = null;
static Integer mutex;
String root;
SyncPrimitive(String address) {
if(zk == null){
try {
System.out.println("Starting ZK:");
zk = new ZooKeeper(address, 3000, this);
mutex = new Integer(-1);
System.out.println("Finished starting ZK: " + zk);
} catch (IOException e) {
System.out.println(e.toString());
zk = null;
}
}
}
synchronized public void process(WatchedEvent event) {
synchronized (mutex) {
mutex.notify();
}
}
Both classes extend SyncPrimitive. In this way, we execute steps that are common to all
primitives in the constructor of SyncPrimitive. To keep the examples simple, we create a
ZooKeeper object the first time we instantiate either a barrier object or a queue object, and
we declare a static variable that is a reference to this object. The subsequent instances of
Barrier and Queue check whether a ZooKeeper object exists. Alternatively, we could have
the application creating a ZooKeeper object and passing it to the constructor of Barrier and
Queue.
We use the process() method to process notifications triggered due to watches. In the
following discussion, we present code that sets watches. A watch is internal structure that
enables ZooKeeper to notify a client of a change to a node. For example, if a client is waiting
for other clients to leave a barrier, then it can set a watch and wait for modifications to a
particular node, which can indicate that it is the end of the wait. This point becomes clear
once we go over the examples.
Programming with ZooKeeper - A basic tutorial
Page 3Copyright © 2008 The Apache Software Foundation. All rights reserved.
2 Barriers
A barrier is a primitive that enables a group of processes to synchronize the beginning and
the end of a computation. The general idea of this implementation is to have a barrier node
that serves the purpose of being a parent for individual process nodes. Suppose that we call
the barrier node "/b1". Each process "p" then creates a node "/b1/p". Once enough processes
have created their corresponding nodes, joined processes can start the computation.
In this example, each process instantiates a Barrier object, and its constructor takes as
parameters:
• the address of a ZooKeeper server (e.g., "zoo1.foo.com:2181")
• the path of the barrier node on ZooKeeper (e.g., "/b1")
• the size of the group of processes
The constructor of Barrier passes the address of the Zookeeper server to the constructor of
the parent class. The parent class creates a ZooKeeper instance if one does not exist. The
constructor of Barrier then creates a barrier node on ZooKeeper, which is the parent node of
all process nodes, and we call root (Note: This is not the ZooKeeper root "/").
/**
* Barrier constructor
*
* @param address
* @param root
* @param size
*/
Barrier(String address, String root, int size) {
super(address);
this.root = root;
this.size = size;
// Create barrier node
if (zk != null) {
try {
Stat s = zk.exists(root, false);
if (s == null) {
zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
}
} catch (KeeperException e) {
System.out
.println("Keeper exception when instantiating queue: "
+ e.toString());
} catch (InterruptedException e) {
System.out.println("Interrupted exception");
}
}
// My node name
try {
name = new
String(InetAddress.getLocalHost().getCanonicalHostName().toString());
Programming with ZooKeeper - A basic tutorial
Page 4Copyright © 2008 The Apache Software Foundation. All rights reserved.
} catch (UnknownHostException e) {
System.out.println(e.toString());
}
}
To enter the barrier, a process calls enter(). The process creates a node under the root to
represent it, using its host name to form the node name. It then wait until enough processes
have entered the barrier. A process does it by checking the number of children the root node
has with "getChildren()", and waiting for notifications in the case it does not have enough.
To receive a notification when there is a change to the root node, a process has to set a watch,
and does it through the call to "getChildren()". In the code, we have that "getChildren()" has
two parameters. The first one states the node to read from, and the second is a boolean flag
that enables the process to set a watch. In the code the flag is true.
/**
* Join barrier
*
* @return
* @throws KeeperException
* @throws InterruptedException
*/
boolean enter() throws KeeperException, InterruptedException{
zk.create(root + "/" + name, new byte[0], Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);
while (true) {
synchronized (mutex) {
List<String> list = zk.getChildren(root, true);
if (list.size() < size) {
mutex.wait();
} else {
return true;
}
}
}
}
Note that enter() throws both KeeperException and InterruptedException, so it is the
reponsability of the application to catch and handle such exceptions.
Once the computation is finished, a process calls leave() to leave the barrier. First it deletes
its corresponding node, and then it gets the children of the root node. If there is at least
one child, then it waits for a notification (obs: note that the second parameter of the call to
getChildren() is true, meaning that ZooKeeper has to set a watch on the the root node). Upon
reception of a notification, it checks once more whether the root node has any child.
/**
* Wait until all reach barrier
Programming with ZooKeeper - A basic tutorial
Page 5Copyright © 2008 The Apache Software Foundation. All rights reserved.
*
* @return
* @throws KeeperException
* @throws InterruptedException
*/
boolean leave() throws KeeperException, InterruptedException{
zk.delete(root + "/" + name, 0);
while (true) {
synchronized (mutex) {
List<String> list = zk.getChildren(root, true);
if (list.size() > 0) {
mutex.wait();
} else {
return true;
}
}
}
}
}
3 Producer-Consumer Queues
A producer-consumer queue is a distributed data estructure thata group of processes use
to generate and consume items. Producer processes create new elements and add them to
the queue. Consumer processes remove elements from the list, and process them. In this
implementation, the elements are simple integers. The queue is represented by a root node,
and to add an element to the queue, a producer process creates a new node, a child of the root
node.
The following excerpt of code corresponds to the constructor of the object. As with Barrier
objects, it first calls the constructor of the parent class, SyncPrimitive, that creates a
ZooKeeper object if one doesn't exist. It then verifies if the root node of the queue exists, and
creates if it doesn't.
/**
* Constructor of producer-consumer queue
*
* @param address
* @param name
*/
Queue(String address, String name) {
super(address);
this.root = name;
// Create ZK node name
if (zk != null) {
try {
Stat s = zk.exists(root, false);
if (s == null) {
zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
}
} catch (KeeperException e) {
Programming with ZooKeeper - A basic tutorial
Page 6Copyright © 2008 The Apache Software Foundation. All rights reserved.
System.out
.println("Keeper exception when instantiating queue: "
+ e.toString());
} catch (InterruptedException e) {
System.out.println("Interrupted exception");
}
}
}
A producer process calls "produce()" to add an element to the queue, and passes an integer
as an argument. To add an element to the queue, the method creates a new node using
"create()", and uses the SEQUENCE flag to instruct ZooKeeper to append the value of the
sequencer counter associated to the root node. In this way, we impose a total order on the
elements of the queue, thus guaranteeing that the oldest element of the queue is the next one
consumed.
/**
* Add element to the queue.
*
* @param i
* @return
*/
boolean produce(int i) throws KeeperException, InterruptedException{
ByteBuffer b = ByteBuffer.allocate(4);
byte[] value;
// Add child with value i
b.putInt(i);
value = b.array();
zk.create(root + "/element", value, Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT_SEQUENTIAL);
return true;
}
To consume an element, a consumer process obtains the children of the root node, reads the
node with smallest counter value, and returns the element. Note that if there is a conflict, then
one of the two contending processes won't be able to delete the node and the delete operation
will throw an exception.
A call to getChildren() returns the list of children in lexicographic order. As lexicographic
order does not necessary follow the numerical order of the counter values, we need to decide
which element is the smallest. To decide which one has the smallest counter value, we
traverse the list, and remove the prefix "element" from each one.
/**
* Remove first element from the queue.
*
* @return
* @throws KeeperException
Programming with ZooKeeper - A basic tutorial
Page 7Copyright © 2008 The Apache Software Foundation. All rights reserved.
* @throws InterruptedException
*/
int consume() throws KeeperException, InterruptedException{
int retvalue = -1;
Stat stat = null;
// Get the first element available
while (true) {
synchronized (mutex) {
List<String> list = zk.getChildren(root, true);
if (list.size() == 0) {
System.out.println("Going to wait");
mutex.wait();
} else {
Integer min = new Integer(list.get(0).substring(7));
for(String s : list){
Integer tempValue = new Integer(s.substring(7));
//System.out.println("Temporary value: " + tempValue);
if(tempValue < min) min = tempValue;
}
System.out.println("Temporary value: " + root + "/element" + min);
byte[] b = zk.getData(root + "/element" + min,
false, stat);
zk.delete(root + "/element" + min, 0);
ByteBuffer buffer = ByteBuffer.wrap(b);
retvalue = buffer.getInt();
return retvalue;
}
}
}
}
}
4 Complete Source Listing
SyncPrimitive.JavaSyncPrimitive.Java
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Random;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.data.Stat;
public class SyncPrimitive implements Watcher {
static ZooKeeper zk = null;
static Integer mutex;
Programming with ZooKeeper - A basic tutorial
Page 8Copyright © 2008 The Apache Software Foundation. All rights reserved.
String root;
SyncPrimitive(String address) {
if(zk == null){
try {
System.out.println("Starting ZK:");
zk = new ZooKeeper(address, 3000, this);
mutex = new Integer(-1);
System.out.println("Finished starting ZK: " + zk);
} catch (IOException e) {
System.out.println(e.toString());
zk = null;
}
}
//else mutex = new Integer(-1);
}
synchronized public void process(WatchedEvent event) {
synchronized (mutex) {
//System.out.println("Process: " + event.getType());
mutex.notify();
}
}
/**
* Barrier
*/
static public class Barrier extends SyncPrimitive {
int size;
String name;
/**
* Barrier constructor
*
* @param address
* @param root
* @param size
*/
Barrier(String address, String root, int size) {
super(address);
this.root = root;
this.size = size;
// Create barrier node
if (zk != null) {
try {
Stat s = zk.exists(root, false);
if (s == null) {
zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
}
} catch (KeeperException e) {
System.out
.println("Keeper exception when instantiating queue: "
+ e.toString());
} catch (InterruptedException e) {
System.out.println("Interrupted exception");
}
}
Programming with ZooKeeper - A basic tutorial
Page 9Copyright © 2008 The Apache Software Foundation. All rights reserved.
// My node name
try {
name = new
String(InetAddress.getLocalHost().getCanonicalHostName().toString());
} catch (UnknownHostException e) {
System.out.println(e.toString());
}
}
/**
* Join barrier
*
* @return
* @throws KeeperException
* @throws InterruptedException
*/
boolean enter() throws KeeperException, InterruptedException{
zk.create(root + "/" + name, new byte[0], Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);
while (true) {
synchronized (mutex) {
List<String> list = zk.getChildren(root, true);
if (list.size() < size) {
mutex.wait();
} else {
return true;
}
}
}
}
/**
* Wait until all reach barrier
*
* @return
* @throws KeeperException
* @throws InterruptedException
*/
boolean leave() throws KeeperException, InterruptedException{
zk.delete(root + "/" + name, 0);
while (true) {
synchronized (mutex) {
List<String> list = zk.getChildren(root, true);
if (list.size() > 0) {
mutex.wait();
} else {
return true;
}
}
}
}
}
/**
* Producer-Consumer queue
Programming with ZooKeeper - A basic tutorial
Page 10Copyright © 2008 The Apache Software Foundation. All rights reserved.
*/
static public class Queue extends SyncPrimitive {
/**
* Constructor of producer-consumer queue
*
* @param address
* @param name
*/
Queue(String address, String name) {
super(address);
this.root = name;
// Create ZK node name
if (zk != null) {
try {
Stat s = zk.exists(root, false);
if (s == null) {
zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
}
} catch (KeeperException e) {
System.out
.println("Keeper exception when instantiating queue: "
+ e.toString());
} catch (InterruptedException e) {
System.out.println("Interrupted exception");
}
}
}
/**
* Add element to the queue.
*
* @param i
* @return
*/
boolean produce(int i) throws KeeperException, InterruptedException{
ByteBuffer b = ByteBuffer.allocate(4);
byte[] value;
// Add child with value i
b.putInt(i);
value = b.array();
zk.create(root + "/element", value, Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT_SEQUENTIAL);
return true;
}
/**
* Remove first element from the queue.
*
* @return
* @throws KeeperException
* @throws InterruptedException
*/
int consume() throws KeeperException, InterruptedException{
int retvalue = -1;
Programming with ZooKeeper - A basic tutorial
Page 11Copyright © 2008 The Apache Software Foundation. All rights reserved.
Stat stat = null;
// Get the first element available
while (true) {
synchronized (mutex) {
List<String> list = zk.getChildren(root, true);
if (list.size() == 0) {
System.out.println("Going to wait");
mutex.wait();
} else {
Integer min = new Integer(list.get(0).substring(7));
for(String s : list){
Integer tempValue = new Integer(s.substring(7));
//System.out.println("Temporary value: " + tempValue);
if(tempValue < min) min = tempValue;
}
System.out.println("Temporary value: " + root + "/element"
+ min);
byte[] b = zk.getData(root + "/element" + min,
false, stat);
zk.delete(root + "/element" + min, 0);
ByteBuffer buffer = ByteBuffer.wrap(b);
retvalue = buffer.getInt();
return retvalue;
}
}
}
}
}
public static void main(String args[]) {
if (args[0].equals("qTest"))
queueTest(args);
else
barrierTest(args);
}
public static void queueTest(String args[]) {
Queue q = new Queue(args[1], "/app1");
System.out.println("Input: " + args[1]);
int i;
Integer max = new Integer(args[2]);
if (args[3].equals("p")) {
System.out.println("Producer");
for (i = 0; i < max; i++)
try{
q.produce(10 + i);
} catch (KeeperException e){
} catch (InterruptedException e){
}
} else {
System.out.println("Consumer");
for (i = 0; i < max; i++) {
Programming with ZooKeeper - A basic tutorial
Page 12Copyright © 2008 The Apache Software Foundation. All rights reserved.
try{
int r = q.consume();
System.out.println("Item: " + r);
} catch (KeeperException e){
i--;
} catch (InterruptedException e){
}
}
}
}
public static void barrierTest(String args[]) {
Barrier b = new Barrier(args[1], "/b1", new Integer(args[2]));
try{
boolean flag = b.enter();
System.out.println("Entered barrier: " + args[2]);
if(!flag) System.out.println("Error when entering the barrier");
} catch (KeeperException e){
} catch (InterruptedException e){
}
// Generate random integer
Random rand = new Random();
int r = rand.nextInt(100);
// Loop for rand iterations
for (int i = 0; i < r; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
try{
b.leave();
} catch (KeeperException e){
} catch (InterruptedException e){
}
System.out.println("Left barrier");
}
}

More Related Content

What's hot (18)

PPTX
Rx for Android & iOS by Harin Trivedi
harintrivedi
 
PDF
JJUG CCC 2011 Spring
Kiyotaka Oku
 
DOCX
Winform
quocphu199
 
PDF
The Ring programming language version 1.5.2 book - Part 13 of 181
Mahmoud Samir Fayed
 
PDF
Understanding Source Code Differences by Separating Refactoring Effects
Institute of Science Tokyo
 
PPTX
Ingesting streaming data for analysis in apache ignite (stream sets theme)
Tom Diederich
 
PDF
Dagger & rxjava & retrofit
Ted Liang
 
PDF
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
julien.ponge
 
PDF
Java 7 LavaJUG
julien.ponge
 
PDF
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...
Paul King
 
PDF
Testing multi outputformat based mapreduce
Ashok Agarwal
 
PDF
Exploring OpenFaaS autoscalability on Kubernetes with the Chaos Toolkit
Sylvain Hellegouarch
 
PDF
Dpilot Source Code With ScreenShots
DeepAnshu Sharma
 
PDF
Source Code for Dpilot
Nidhi Chauhan
 
PPTX
разработка серверов и серверных приложений лекция №4
Eugeniy Tyumentcev
 
PDF
Java libraries you can't afford to miss
Andres Almiray
 
KEY
Android workshop
Michael Galpin
 
PPTX
IPC: AIDL is sexy, not a curse
Yonatan Levin
 
Rx for Android & iOS by Harin Trivedi
harintrivedi
 
JJUG CCC 2011 Spring
Kiyotaka Oku
 
Winform
quocphu199
 
The Ring programming language version 1.5.2 book - Part 13 of 181
Mahmoud Samir Fayed
 
Understanding Source Code Differences by Separating Refactoring Effects
Institute of Science Tokyo
 
Ingesting streaming data for analysis in apache ignite (stream sets theme)
Tom Diederich
 
Dagger & rxjava & retrofit
Ted Liang
 
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
julien.ponge
 
Java 7 LavaJUG
julien.ponge
 
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...
Paul King
 
Testing multi outputformat based mapreduce
Ashok Agarwal
 
Exploring OpenFaaS autoscalability on Kubernetes with the Chaos Toolkit
Sylvain Hellegouarch
 
Dpilot Source Code With ScreenShots
DeepAnshu Sharma
 
Source Code for Dpilot
Nidhi Chauhan
 
разработка серверов и серверных приложений лекция №4
Eugeniy Tyumentcev
 
Java libraries you can't afford to miss
Andres Almiray
 
Android workshop
Michael Galpin
 
IPC: AIDL is sexy, not a curse
Yonatan Levin
 

Similar to Programming with ZooKeeper - A basic tutorial (20)

PDF
ZooKeeper Recipes and Solutions
Jeff Smith
 
PDF
ZooKeeper Recipes and Solutions
Jeff Smith
 
PDF
ZooKeeper Recipes and Solutions
Jeff Smith
 
PPTX
Winter is coming? Not if ZooKeeper is there!
Joydeep Banik Roy
 
PDF
Apache Zookeeper
Nguyen Quang
 
PPTX
Apache zookeeper seminar_trinh_viet_dung_03_2016
Viet-Dung TRINH
 
PPTX
Apache Zookeeper Explained: Tutorial, Use Cases and Zookeeper Java API Examples
Binu George
 
PDF
Introduction to ZooKeeper - TriHUG May 22, 2012
mumrah
 
PPTX
Zookeeper Architecture
Prasad Wali
 
PPTX
Apache zookeeper 101
Quach Tung
 
PDF
Apache ZooKeeper
Scott Leberknight
 
PDF
zookeeperProgrammers
Hiroshi Ono
 
PPT
Zookeeper Introduce
jhao niu
 
PDF
Introduction to Apache ZooKeeper | Big Data Hadoop Spark Tutorial | CloudxLab
CloudxLab
 
PPTX
ZeroMq ZooKeeper and FlatBuffers
Ravi Okade
 
PPTX
Zookeeper Tutorial for beginners
jeetendra mandal
 
PPTX
Leo's Notes about Apache Kafka
Léopold Gault
 
PPTX
Introduction to apache zoo keeper
Omid Vahdaty
 
PPTX
Distributed Applications with Apache Zookeeper
Alex Ehrnschwender
 
PDF
Apache ZooKeeper TechTuesday
Andrei Savu
 
ZooKeeper Recipes and Solutions
Jeff Smith
 
ZooKeeper Recipes and Solutions
Jeff Smith
 
ZooKeeper Recipes and Solutions
Jeff Smith
 
Winter is coming? Not if ZooKeeper is there!
Joydeep Banik Roy
 
Apache Zookeeper
Nguyen Quang
 
Apache zookeeper seminar_trinh_viet_dung_03_2016
Viet-Dung TRINH
 
Apache Zookeeper Explained: Tutorial, Use Cases and Zookeeper Java API Examples
Binu George
 
Introduction to ZooKeeper - TriHUG May 22, 2012
mumrah
 
Zookeeper Architecture
Prasad Wali
 
Apache zookeeper 101
Quach Tung
 
Apache ZooKeeper
Scott Leberknight
 
zookeeperProgrammers
Hiroshi Ono
 
Zookeeper Introduce
jhao niu
 
Introduction to Apache ZooKeeper | Big Data Hadoop Spark Tutorial | CloudxLab
CloudxLab
 
ZeroMq ZooKeeper and FlatBuffers
Ravi Okade
 
Zookeeper Tutorial for beginners
jeetendra mandal
 
Leo's Notes about Apache Kafka
Léopold Gault
 
Introduction to apache zoo keeper
Omid Vahdaty
 
Distributed Applications with Apache Zookeeper
Alex Ehrnschwender
 
Apache ZooKeeper TechTuesday
Andrei Savu
 
Ad

More from Jeff Smith (20)

PDF
vi-vim-cheat-sheet.pdf
Jeff Smith
 
PPTX
dfgdgsdg
Jeff Smith
 
PDF
3yudh.pdf
Jeff Smith
 
PDF
nvjiz.pdf
Jeff Smith
 
PDF
nvjiz.pdf
Jeff Smith
 
PDF
nvjiz.pdf
Jeff Smith
 
PDF
nvjiz.pdf
Jeff Smith
 
PDF
nvjiz.pdf
Jeff Smith
 
PDF
mctpr.pdf
Jeff Smith
 
PDF
mctpr.pdf
Jeff Smith
 
PDF
mctpr.pdf
Jeff Smith
 
PDF
mctpr.pdf
Jeff Smith
 
PDF
mctpr.pdf
Jeff Smith
 
PDF
0nba4.pdf
Jeff Smith
 
PDF
0nba4.pdf
Jeff Smith
 
PDF
4wa4i.pdf
Jeff Smith
 
PDF
7k3gy.pdf
Jeff Smith
 
PDF
b33t2.pdf
Jeff Smith
 
PDF
cqqk2.pdf
Jeff Smith
 
DOCX
ebcbe.docx
Jeff Smith
 
vi-vim-cheat-sheet.pdf
Jeff Smith
 
dfgdgsdg
Jeff Smith
 
3yudh.pdf
Jeff Smith
 
nvjiz.pdf
Jeff Smith
 
nvjiz.pdf
Jeff Smith
 
nvjiz.pdf
Jeff Smith
 
nvjiz.pdf
Jeff Smith
 
nvjiz.pdf
Jeff Smith
 
mctpr.pdf
Jeff Smith
 
mctpr.pdf
Jeff Smith
 
mctpr.pdf
Jeff Smith
 
mctpr.pdf
Jeff Smith
 
mctpr.pdf
Jeff Smith
 
0nba4.pdf
Jeff Smith
 
0nba4.pdf
Jeff Smith
 
4wa4i.pdf
Jeff Smith
 
7k3gy.pdf
Jeff Smith
 
b33t2.pdf
Jeff Smith
 
cqqk2.pdf
Jeff Smith
 
ebcbe.docx
Jeff Smith
 
Ad

Recently uploaded (20)

PPSX
Usergroup - OutSystems Architecture.ppsx
Kurt Vandevelde
 
PPTX
Practical Applications of AI in Local Government
OnBoard
 
PDF
My Journey from CAD to BIM: A True Underdog Story
Safe Software
 
PDF
Pipeline Industry IoT - Real Time Data Monitoring
Safe Software
 
PPTX
Reimaginando la Ciberdefensa: De Copilots a Redes de Agentes
Cristian Garcia G.
 
PDF
Understanding The True Cost of DynamoDB Webinar
ScyllaDB
 
PDF
Automating the Geo-Referencing of Historic Aerial Photography in Flanders
Safe Software
 
PDF
5 Things to Consider When Deploying AI in Your Enterprise
Safe Software
 
PDF
Why aren't you using FME Flow's CPU Time?
Safe Software
 
PDF
Proactive Server and System Monitoring with FME: Using HTTP and System Caller...
Safe Software
 
PDF
Unlocking FME Flow’s Potential: Architecture Design for Modern Enterprises
Safe Software
 
PDF
Quantum AI Discoveries: Fractal Patterns Consciousness and Cyclical Universes
Saikat Basu
 
PDF
Optimizing the trajectory of a wheel loader working in short loading cycles
Reno Filla
 
PPTX
MARTSIA: A Tool for Confidential Data Exchange via Public Blockchain - Poster...
Michele Kryston
 
PDF
Darley - FIRST Copenhagen Lightning Talk (2025-06-26) Epochalypse 2038 - Time...
treyka
 
PPTX
The birth and death of Stars - earth and life science
rizellemarieastrolo
 
PDF
FME as an Orchestration Tool with Principles From Data Gravity
Safe Software
 
PPTX
2025 HackRedCon Cyber Career Paths.pptx Scott Stanton
Scott Stanton
 
PDF
How to Visualize the ​Spatio-Temporal Data Using CesiumJS​
SANGHEE SHIN
 
PDF
The Future of Product Management in AI ERA.pdf
Alyona Owens
 
Usergroup - OutSystems Architecture.ppsx
Kurt Vandevelde
 
Practical Applications of AI in Local Government
OnBoard
 
My Journey from CAD to BIM: A True Underdog Story
Safe Software
 
Pipeline Industry IoT - Real Time Data Monitoring
Safe Software
 
Reimaginando la Ciberdefensa: De Copilots a Redes de Agentes
Cristian Garcia G.
 
Understanding The True Cost of DynamoDB Webinar
ScyllaDB
 
Automating the Geo-Referencing of Historic Aerial Photography in Flanders
Safe Software
 
5 Things to Consider When Deploying AI in Your Enterprise
Safe Software
 
Why aren't you using FME Flow's CPU Time?
Safe Software
 
Proactive Server and System Monitoring with FME: Using HTTP and System Caller...
Safe Software
 
Unlocking FME Flow’s Potential: Architecture Design for Modern Enterprises
Safe Software
 
Quantum AI Discoveries: Fractal Patterns Consciousness and Cyclical Universes
Saikat Basu
 
Optimizing the trajectory of a wheel loader working in short loading cycles
Reno Filla
 
MARTSIA: A Tool for Confidential Data Exchange via Public Blockchain - Poster...
Michele Kryston
 
Darley - FIRST Copenhagen Lightning Talk (2025-06-26) Epochalypse 2038 - Time...
treyka
 
The birth and death of Stars - earth and life science
rizellemarieastrolo
 
FME as an Orchestration Tool with Principles From Data Gravity
Safe Software
 
2025 HackRedCon Cyber Career Paths.pptx Scott Stanton
Scott Stanton
 
How to Visualize the ​Spatio-Temporal Data Using CesiumJS​
SANGHEE SHIN
 
The Future of Product Management in AI ERA.pdf
Alyona Owens
 

Programming with ZooKeeper - A basic tutorial

  • 1. Copyright © 2008 The Apache Software Foundation. All rights reserved. Programming with ZooKeeper - A basic tutorial by Table of contents 1 Introduction........................................................................................................................ 2 2 Barriers............................................................................................................................... 3 3 Producer-Consumer Queues...............................................................................................5 4 Complete Source Listing....................................................................................................7
  • 2. Programming with ZooKeeper - A basic tutorial Page 2Copyright © 2008 The Apache Software Foundation. All rights reserved. 1 Introduction In this tutorial, we show simple implementations of barriers and producer-consumer queues using ZooKeeper. We call the respective classes Barrier and Queue. These examples assume that you have at least one ZooKeeper server running. Both primitives use the following common excerpt of code: static ZooKeeper zk = null; static Integer mutex; String root; SyncPrimitive(String address) { if(zk == null){ try { System.out.println("Starting ZK:"); zk = new ZooKeeper(address, 3000, this); mutex = new Integer(-1); System.out.println("Finished starting ZK: " + zk); } catch (IOException e) { System.out.println(e.toString()); zk = null; } } } synchronized public void process(WatchedEvent event) { synchronized (mutex) { mutex.notify(); } } Both classes extend SyncPrimitive. In this way, we execute steps that are common to all primitives in the constructor of SyncPrimitive. To keep the examples simple, we create a ZooKeeper object the first time we instantiate either a barrier object or a queue object, and we declare a static variable that is a reference to this object. The subsequent instances of Barrier and Queue check whether a ZooKeeper object exists. Alternatively, we could have the application creating a ZooKeeper object and passing it to the constructor of Barrier and Queue. We use the process() method to process notifications triggered due to watches. In the following discussion, we present code that sets watches. A watch is internal structure that enables ZooKeeper to notify a client of a change to a node. For example, if a client is waiting for other clients to leave a barrier, then it can set a watch and wait for modifications to a particular node, which can indicate that it is the end of the wait. This point becomes clear once we go over the examples.
  • 3. Programming with ZooKeeper - A basic tutorial Page 3Copyright © 2008 The Apache Software Foundation. All rights reserved. 2 Barriers A barrier is a primitive that enables a group of processes to synchronize the beginning and the end of a computation. The general idea of this implementation is to have a barrier node that serves the purpose of being a parent for individual process nodes. Suppose that we call the barrier node "/b1". Each process "p" then creates a node "/b1/p". Once enough processes have created their corresponding nodes, joined processes can start the computation. In this example, each process instantiates a Barrier object, and its constructor takes as parameters: • the address of a ZooKeeper server (e.g., "zoo1.foo.com:2181") • the path of the barrier node on ZooKeeper (e.g., "/b1") • the size of the group of processes The constructor of Barrier passes the address of the Zookeeper server to the constructor of the parent class. The parent class creates a ZooKeeper instance if one does not exist. The constructor of Barrier then creates a barrier node on ZooKeeper, which is the parent node of all process nodes, and we call root (Note: This is not the ZooKeeper root "/"). /** * Barrier constructor * * @param address * @param root * @param size */ Barrier(String address, String root, int size) { super(address); this.root = root; this.size = size; // Create barrier node if (zk != null) { try { Stat s = zk.exists(root, false); if (s == null) { zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } } catch (KeeperException e) { System.out .println("Keeper exception when instantiating queue: " + e.toString()); } catch (InterruptedException e) { System.out.println("Interrupted exception"); } } // My node name try { name = new String(InetAddress.getLocalHost().getCanonicalHostName().toString());
  • 4. Programming with ZooKeeper - A basic tutorial Page 4Copyright © 2008 The Apache Software Foundation. All rights reserved. } catch (UnknownHostException e) { System.out.println(e.toString()); } } To enter the barrier, a process calls enter(). The process creates a node under the root to represent it, using its host name to form the node name. It then wait until enough processes have entered the barrier. A process does it by checking the number of children the root node has with "getChildren()", and waiting for notifications in the case it does not have enough. To receive a notification when there is a change to the root node, a process has to set a watch, and does it through the call to "getChildren()". In the code, we have that "getChildren()" has two parameters. The first one states the node to read from, and the second is a boolean flag that enables the process to set a watch. In the code the flag is true. /** * Join barrier * * @return * @throws KeeperException * @throws InterruptedException */ boolean enter() throws KeeperException, InterruptedException{ zk.create(root + "/" + name, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); while (true) { synchronized (mutex) { List<String> list = zk.getChildren(root, true); if (list.size() < size) { mutex.wait(); } else { return true; } } } } Note that enter() throws both KeeperException and InterruptedException, so it is the reponsability of the application to catch and handle such exceptions. Once the computation is finished, a process calls leave() to leave the barrier. First it deletes its corresponding node, and then it gets the children of the root node. If there is at least one child, then it waits for a notification (obs: note that the second parameter of the call to getChildren() is true, meaning that ZooKeeper has to set a watch on the the root node). Upon reception of a notification, it checks once more whether the root node has any child. /** * Wait until all reach barrier
  • 5. Programming with ZooKeeper - A basic tutorial Page 5Copyright © 2008 The Apache Software Foundation. All rights reserved. * * @return * @throws KeeperException * @throws InterruptedException */ boolean leave() throws KeeperException, InterruptedException{ zk.delete(root + "/" + name, 0); while (true) { synchronized (mutex) { List<String> list = zk.getChildren(root, true); if (list.size() > 0) { mutex.wait(); } else { return true; } } } } } 3 Producer-Consumer Queues A producer-consumer queue is a distributed data estructure thata group of processes use to generate and consume items. Producer processes create new elements and add them to the queue. Consumer processes remove elements from the list, and process them. In this implementation, the elements are simple integers. The queue is represented by a root node, and to add an element to the queue, a producer process creates a new node, a child of the root node. The following excerpt of code corresponds to the constructor of the object. As with Barrier objects, it first calls the constructor of the parent class, SyncPrimitive, that creates a ZooKeeper object if one doesn't exist. It then verifies if the root node of the queue exists, and creates if it doesn't. /** * Constructor of producer-consumer queue * * @param address * @param name */ Queue(String address, String name) { super(address); this.root = name; // Create ZK node name if (zk != null) { try { Stat s = zk.exists(root, false); if (s == null) { zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } } catch (KeeperException e) {
  • 6. Programming with ZooKeeper - A basic tutorial Page 6Copyright © 2008 The Apache Software Foundation. All rights reserved. System.out .println("Keeper exception when instantiating queue: " + e.toString()); } catch (InterruptedException e) { System.out.println("Interrupted exception"); } } } A producer process calls "produce()" to add an element to the queue, and passes an integer as an argument. To add an element to the queue, the method creates a new node using "create()", and uses the SEQUENCE flag to instruct ZooKeeper to append the value of the sequencer counter associated to the root node. In this way, we impose a total order on the elements of the queue, thus guaranteeing that the oldest element of the queue is the next one consumed. /** * Add element to the queue. * * @param i * @return */ boolean produce(int i) throws KeeperException, InterruptedException{ ByteBuffer b = ByteBuffer.allocate(4); byte[] value; // Add child with value i b.putInt(i); value = b.array(); zk.create(root + "/element", value, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL); return true; } To consume an element, a consumer process obtains the children of the root node, reads the node with smallest counter value, and returns the element. Note that if there is a conflict, then one of the two contending processes won't be able to delete the node and the delete operation will throw an exception. A call to getChildren() returns the list of children in lexicographic order. As lexicographic order does not necessary follow the numerical order of the counter values, we need to decide which element is the smallest. To decide which one has the smallest counter value, we traverse the list, and remove the prefix "element" from each one. /** * Remove first element from the queue. * * @return * @throws KeeperException
  • 7. Programming with ZooKeeper - A basic tutorial Page 7Copyright © 2008 The Apache Software Foundation. All rights reserved. * @throws InterruptedException */ int consume() throws KeeperException, InterruptedException{ int retvalue = -1; Stat stat = null; // Get the first element available while (true) { synchronized (mutex) { List<String> list = zk.getChildren(root, true); if (list.size() == 0) { System.out.println("Going to wait"); mutex.wait(); } else { Integer min = new Integer(list.get(0).substring(7)); for(String s : list){ Integer tempValue = new Integer(s.substring(7)); //System.out.println("Temporary value: " + tempValue); if(tempValue < min) min = tempValue; } System.out.println("Temporary value: " + root + "/element" + min); byte[] b = zk.getData(root + "/element" + min, false, stat); zk.delete(root + "/element" + min, 0); ByteBuffer buffer = ByteBuffer.wrap(b); retvalue = buffer.getInt(); return retvalue; } } } } } 4 Complete Source Listing SyncPrimitive.JavaSyncPrimitive.Java import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.util.List; import java.util.Random; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.data.Stat; public class SyncPrimitive implements Watcher { static ZooKeeper zk = null; static Integer mutex;
  • 8. Programming with ZooKeeper - A basic tutorial Page 8Copyright © 2008 The Apache Software Foundation. All rights reserved. String root; SyncPrimitive(String address) { if(zk == null){ try { System.out.println("Starting ZK:"); zk = new ZooKeeper(address, 3000, this); mutex = new Integer(-1); System.out.println("Finished starting ZK: " + zk); } catch (IOException e) { System.out.println(e.toString()); zk = null; } } //else mutex = new Integer(-1); } synchronized public void process(WatchedEvent event) { synchronized (mutex) { //System.out.println("Process: " + event.getType()); mutex.notify(); } } /** * Barrier */ static public class Barrier extends SyncPrimitive { int size; String name; /** * Barrier constructor * * @param address * @param root * @param size */ Barrier(String address, String root, int size) { super(address); this.root = root; this.size = size; // Create barrier node if (zk != null) { try { Stat s = zk.exists(root, false); if (s == null) { zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } } catch (KeeperException e) { System.out .println("Keeper exception when instantiating queue: " + e.toString()); } catch (InterruptedException e) { System.out.println("Interrupted exception"); } }
  • 9. Programming with ZooKeeper - A basic tutorial Page 9Copyright © 2008 The Apache Software Foundation. All rights reserved. // My node name try { name = new String(InetAddress.getLocalHost().getCanonicalHostName().toString()); } catch (UnknownHostException e) { System.out.println(e.toString()); } } /** * Join barrier * * @return * @throws KeeperException * @throws InterruptedException */ boolean enter() throws KeeperException, InterruptedException{ zk.create(root + "/" + name, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); while (true) { synchronized (mutex) { List<String> list = zk.getChildren(root, true); if (list.size() < size) { mutex.wait(); } else { return true; } } } } /** * Wait until all reach barrier * * @return * @throws KeeperException * @throws InterruptedException */ boolean leave() throws KeeperException, InterruptedException{ zk.delete(root + "/" + name, 0); while (true) { synchronized (mutex) { List<String> list = zk.getChildren(root, true); if (list.size() > 0) { mutex.wait(); } else { return true; } } } } } /** * Producer-Consumer queue
  • 10. Programming with ZooKeeper - A basic tutorial Page 10Copyright © 2008 The Apache Software Foundation. All rights reserved. */ static public class Queue extends SyncPrimitive { /** * Constructor of producer-consumer queue * * @param address * @param name */ Queue(String address, String name) { super(address); this.root = name; // Create ZK node name if (zk != null) { try { Stat s = zk.exists(root, false); if (s == null) { zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } } catch (KeeperException e) { System.out .println("Keeper exception when instantiating queue: " + e.toString()); } catch (InterruptedException e) { System.out.println("Interrupted exception"); } } } /** * Add element to the queue. * * @param i * @return */ boolean produce(int i) throws KeeperException, InterruptedException{ ByteBuffer b = ByteBuffer.allocate(4); byte[] value; // Add child with value i b.putInt(i); value = b.array(); zk.create(root + "/element", value, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL); return true; } /** * Remove first element from the queue. * * @return * @throws KeeperException * @throws InterruptedException */ int consume() throws KeeperException, InterruptedException{ int retvalue = -1;
  • 11. Programming with ZooKeeper - A basic tutorial Page 11Copyright © 2008 The Apache Software Foundation. All rights reserved. Stat stat = null; // Get the first element available while (true) { synchronized (mutex) { List<String> list = zk.getChildren(root, true); if (list.size() == 0) { System.out.println("Going to wait"); mutex.wait(); } else { Integer min = new Integer(list.get(0).substring(7)); for(String s : list){ Integer tempValue = new Integer(s.substring(7)); //System.out.println("Temporary value: " + tempValue); if(tempValue < min) min = tempValue; } System.out.println("Temporary value: " + root + "/element" + min); byte[] b = zk.getData(root + "/element" + min, false, stat); zk.delete(root + "/element" + min, 0); ByteBuffer buffer = ByteBuffer.wrap(b); retvalue = buffer.getInt(); return retvalue; } } } } } public static void main(String args[]) { if (args[0].equals("qTest")) queueTest(args); else barrierTest(args); } public static void queueTest(String args[]) { Queue q = new Queue(args[1], "/app1"); System.out.println("Input: " + args[1]); int i; Integer max = new Integer(args[2]); if (args[3].equals("p")) { System.out.println("Producer"); for (i = 0; i < max; i++) try{ q.produce(10 + i); } catch (KeeperException e){ } catch (InterruptedException e){ } } else { System.out.println("Consumer"); for (i = 0; i < max; i++) {
  • 12. Programming with ZooKeeper - A basic tutorial Page 12Copyright © 2008 The Apache Software Foundation. All rights reserved. try{ int r = q.consume(); System.out.println("Item: " + r); } catch (KeeperException e){ i--; } catch (InterruptedException e){ } } } } public static void barrierTest(String args[]) { Barrier b = new Barrier(args[1], "/b1", new Integer(args[2])); try{ boolean flag = b.enter(); System.out.println("Entered barrier: " + args[2]); if(!flag) System.out.println("Error when entering the barrier"); } catch (KeeperException e){ } catch (InterruptedException e){ } // Generate random integer Random rand = new Random(); int r = rand.nextInt(100); // Loop for rand iterations for (int i = 0; i < r; i++) { try { Thread.sleep(100); } catch (InterruptedException e) { } } try{ b.leave(); } catch (KeeperException e){ } catch (InterruptedException e){ } System.out.println("Left barrier"); } }