Zookeeper 进阶之——Zookeeper编程示例(如何使用Zookeeper实现屏障Barriers和队列Queues)...

本文主要是介绍Zookeeper 进阶之——Zookeeper编程示例(如何使用Zookeeper实现屏障Barriers和队列Queues)...,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

[quote]原文:http://www.cnblogs.com/haippy/archive/2012/07/26/2609769.html
[/quote]
[b]引言[/b]

本文将告诉你如何使用 Zookeeper 实现两种常用的分布式数据结构,屏障(barriers) 和队列(queues),我们为此还分别实现了两个类:Barrier and Queue. 本文中的例子假设你已经成功运行了Zookeeper服务器。

上述两种最基本的原语都使用了下面的常见编码规范:

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();        }    }

以上两个类都扩展了 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.

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());            } 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         *         * @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 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) {                    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         * @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;                    }                }            }        }    }


[b]完整例子[/b]

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;    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");                }            }            // 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     */    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;            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++) {                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");    }}

这篇关于Zookeeper 进阶之——Zookeeper编程示例(如何使用Zookeeper实现屏障Barriers和队列Queues)...的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1114438

相关文章

Python使用openpyxl读取Excel的操作详解

《Python使用openpyxl读取Excel的操作详解》本文介绍了使用Python的openpyxl库进行Excel文件的创建、读写、数据操作、工作簿与工作表管理,包括创建工作簿、加载工作簿、操作... 目录1 概述1.1 图示1.2 安装第三方库2 工作簿 workbook2.1 创建:Workboo

SpringBoot集成EasyPoi实现Excel模板导出成PDF文件

《SpringBoot集成EasyPoi实现Excel模板导出成PDF文件》在日常工作中,我们经常需要将数据导出成Excel表格或PDF文件,本文将介绍如何在SpringBoot项目中集成EasyPo... 目录前言摘要简介源代码解析应用场景案例优缺点分析类代码方法介绍测试用例小结前言在日常工作中,我们经

基于Python实现简易视频剪辑工具

《基于Python实现简易视频剪辑工具》这篇文章主要为大家详细介绍了如何用Python打造一个功能完备的简易视频剪辑工具,包括视频文件导入与格式转换,基础剪辑操作,音频处理等功能,感兴趣的小伙伴可以了... 目录一、技术选型与环境搭建二、核心功能模块实现1. 视频基础操作2. 音频处理3. 特效与转场三、高

Python实现中文文本处理与分析程序的示例详解

《Python实现中文文本处理与分析程序的示例详解》在当今信息爆炸的时代,文本数据的处理与分析成为了数据科学领域的重要课题,本文将使用Python开发一款基于Python的中文文本处理与分析程序,希望... 目录一、程序概述二、主要功能解析2.1 文件操作2.2 基础分析2.3 高级分析2.4 可视化2.5

Java实现预览与打印功能详解

《Java实现预览与打印功能详解》在Java中,打印功能主要依赖java.awt.print包,该包提供了与打印相关的一些关键类,比如PrinterJob和PageFormat,它们构成... 目录Java 打印系统概述打印预览与设置使用 PageFormat 和 PrinterJob 类设置页面格式与纸张

使用Go实现文件复制的完整流程

《使用Go实现文件复制的完整流程》本案例将实现一个实用的文件操作工具:将一个文件的内容完整复制到另一个文件中,这是文件处理中的常见任务,比如配置文件备份、日志迁移、用户上传文件转存等,文中通过代码示例... 目录案例说明涉及China编程知识点示例代码代码解析示例运行练习扩展小结案例说明我们将通过标准库 os

MySQL 8 中的一个强大功能 JSON_TABLE示例详解

《MySQL8中的一个强大功能JSON_TABLE示例详解》JSON_TABLE是MySQL8中引入的一个强大功能,它允许用户将JSON数据转换为关系表格式,从而可以更方便地在SQL查询中处理J... 目录基本语法示例示例查询解释应用场景不适用场景1. ‌jsON 数据结构过于复杂或动态变化‌2. ‌性能要

postgresql使用UUID函数的方法

《postgresql使用UUID函数的方法》本文给大家介绍postgresql使用UUID函数的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录PostgreSQL有两种生成uuid的方法。可以先通过sql查看是否已安装扩展函数,和可以安装的扩展函数

Python实现终端清屏的几种方式详解

《Python实现终端清屏的几种方式详解》在使用Python进行终端交互式编程时,我们经常需要清空当前终端屏幕的内容,本文为大家整理了几种常见的实现方法,有需要的小伙伴可以参考下... 目录方法一:使用 `os` 模块调用系统命令方法二:使用 `subprocess` 模块执行命令方法三:打印多个换行符模拟

SpringBoot+EasyPOI轻松实现Excel和Word导出PDF

《SpringBoot+EasyPOI轻松实现Excel和Word导出PDF》在企业级开发中,将Excel和Word文档导出为PDF是常见需求,本文将结合​​EasyPOI和​​Aspose系列工具实... 目录一、环境准备与依赖配置1.1 方案选型1.2 依赖配置(商业库方案)二、Excel 导出 PDF