zookeeper分布式队列

一、简介

在此介绍基于zookeeper实现的分布式队列。包括类似jdk队列的简单队列SimpleDistributedQueue、

分布式队列DistributedQueue、带Id的分布式队列DistributedIdQueue、带优先级的分布式队列DistributedPriorityQueue。

二、添加maven依赖


    org.apache.zookeeper
    zookeeper
    3.4.6


    org.apache.curator
    curator-framework
    4.0.0


    org.apache.curator
    curator-client
    4.0.0


    org.apache.curator
    curator-recipes
    4.0.0
三、简单队列SimpleDistributedQueue

简单队列SimpleDistributedQueue和jdk中队列类似,拥有offer()、take()方法。

示例代码:

import org.apache.commons.lang3.StringUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.queue.SimpleDistributedQueue;
import org.apache.curator.retry.ExponentialBackoffRetry;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

public class ZookeeperSimpleDistributedQueueMain {
    public static void main(String[] args) throws Exception {
        //创建zookeeper客户端
        CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", new ExponentialBackoffRetry(1000, 3));
        client.start();

        //指定锁路径
        String lockPath = "/zkLockRoot/lock_1";
        //创建分布式队列
        SimpleDistributedQueue simpleDistributedQueue = new SimpleDistributedQueue(client,lockPath);

        //生成线程池
        ExecutorService executor = Executors.newCachedThreadPool();
        //生产
        BiConsumer,String> putConsumer = (queue, item) -> {
            try {
                Callable call = () -> {
                    try {
                        TimeUnit.SECONDS.sleep((int)(Math.random()*10));
                        //向队尾中添加数据
                        queue.offer(item.getBytes());
                        System.out.println(Thread.currentThread() + "  put : "+ item);
                    } catch (Exception e) {
                    }
                    return true;
                };
                executor.submit(call);
            } catch (Exception e) {
            }
        };
        //消费
        Consumer getConsumer = (queue) -> {
            try {
                Callable call = () -> {
                    try {
                        while(true){
                            //从队首取出数据
                            byte[] dataByte = queue.take();
                            String data = new String(dataByte);
                            if(StringUtils.isBlank(data)){
                                break;
                            }
                            System.out.println(Thread.currentThread() + "  get : "+ data);
                        }
                    } catch (Exception e) {
                    }
                    return true;
                };
                executor.submit(call);
            } catch (Exception e) {
            }
        };

        //分布式队列测试(5个线程生产)
        System.out.println("5个并发线程生产,测试分布式队列");
        //5个生产线程
        for (int i = 0; i < 10; i++) {
            putConsumer.accept(simpleDistributedQueue, "item"+i);
        }
        //分布式队列测试(2个线程生产)
        System.out.println("2个并发线程消息,测试分布式队列");
        //2个消费线程
        for (int i = 0; i < 2; i++) {
            getConsumer.accept(simpleDistributedQueue);
        }

        executor.shutdown();
        TimeUnit.SECONDS.sleep(20);
        client.close();
    }
}
输出:

Thread[pool-3-thread-10,5,main]  put : item9
Thread[pool-3-thread-12,5,main]  get : item9
Thread[pool-3-thread-4,5,main]  put : item3
Thread[pool-3-thread-12,5,main]  get : item3
Thread[pool-3-thread-3,5,main]  put : item2
Thread[pool-3-thread-12,5,main]  get : item2
Thread[pool-3-thread-6,5,main]  put : item5
Thread[pool-3-thread-12,5,main]  get : item5
Thread[pool-3-thread-5,5,main]  put : item4
Thread[pool-3-thread-9,5,main]  put : item8
Thread[pool-3-thread-11,5,main]  get : item4
Thread[pool-3-thread-12,5,main]  get : item8
Thread[pool-3-thread-7,5,main]  put : item6
Thread[pool-3-thread-8,5,main]  put : item7
Thread[pool-3-thread-11,5,main]  get : item6
Thread[pool-3-thread-12,5,main]  get : item7
Thread[pool-3-thread-2,5,main]  put : item1
Thread[pool-3-thread-1,5,main]  put : item0
Thread[pool-3-thread-11,5,main]  get : item1
Thread[pool-3-thread-12,5,main]  get : item0

四、分布式队列DistributedQueue

分布式队列DistributedQueue和消息队列类似,需要定义消费监听器、序列化方式。

示例代码:

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.queue.DistributedQueue;
import org.apache.curator.framework.recipes.queue.QueueBuilder;
import org.apache.curator.framework.recipes.queue.QueueConsumer;
import org.apache.curator.framework.recipes.queue.QueueSerializer;
import org.apache.curator.framework.state.ConnectionState;
import org.apache.curator.retry.ExponentialBackoffRetry;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;

public class ZookeeperDistributedQueueMain {
    public static void main(String[] args) throws Exception {
        //创建zookeeper客户端
        CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", new ExponentialBackoffRetry(1000, 3));
        client.start();

        //指定锁路径
        String lockPath = "/zkLockRoot/lock_1";

        //消费监听器
        QueueConsumer queueConsumer = new QueueConsumer() {
            //消费队列数据
            @Override
            public void consumeMessage(String message) throws Exception {
                System.out.println("message: " + message);
            }

            @Override
            public void stateChanged(CuratorFramework client, ConnectionState newState) {

            }
        };

        //序列化
        QueueSerializer queueSerializer = new QueueSerializer() {
            @Override
            public byte[] serialize(String item) {
                return item.getBytes();
            }

            @Override
            public String deserialize(byte[] bytes) {
                return new String(bytes);
            }
        };

        //创建分布式队列
        QueueBuilder distributedBuilder = QueueBuilder.builder(client, queueConsumer, queueSerializer, lockPath);
        DistributedQueue distributedQueue = distributedBuilder.buildQueue();
        distributedQueue.start();

        //生成线程池
        ExecutorService executor = Executors.newCachedThreadPool();
        //生产
        BiConsumer, String> putConsumer = (queue, item) -> {
            try {
                Callable call = () -> {
                    try {
                        //向队尾添加数据
                        queue.put(item);
                        System.out.println(Thread.currentThread() + "  put : "+ item);
                    } catch (Exception e) {
                    }
                    return true;
                };
                executor.submit(call);
            } catch (Exception e) {
            }
        };

        //分布式队列测试(5个线程生产)
        System.out.println("5个并发线程生产,测试分布式队列");
        //5个生产线程
        for (int i = 0; i < 5; i++) {
            putConsumer.accept(distributedQueue, "item"+i);
        }

        executor.shutdown();
        TimeUnit.SECONDS.sleep(20);
        distributedQueue.close();
        client.close();
    }
}
输出:

5个并发线程生产,测试分布式队列
Thread[pool-4-thread-2,5,main]  put : item1
Thread[pool-4-thread-1,5,main]  put : item0
Thread[pool-4-thread-3,5,main]  put : item2
Thread[pool-4-thread-5,5,main]  put : item4
Thread[pool-4-thread-4,5,main]  put : item3
message: item1
message: item0
message: item2
message: item4
message: item3

五、带Id的分布式队列DistributedIdQueue

带Id的分布式队列DistributedIdQueue每条数据可以指定id,也可根据此id对数据进行删除等操作,

其它的和分布式队列DistributedQueue类似。

示例代码:

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.queue.*;
import org.apache.curator.framework.state.ConnectionState;
import org.apache.curator.retry.ExponentialBackoffRetry;

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;

public class ZookeeperDistributedIdQueueMain {
    public static void main(String[] args) throws Exception {
        //创建zookeeper客户端
        CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", new ExponentialBackoffRetry(1000, 3));
        client.start();

        //指定锁路径
        String lockPath = "/zkLockRoot/lock_1";

        //消费者
        QueueConsumer queueConsumer = new QueueConsumer() {
            @Override
            public void consumeMessage(String message) throws Exception {
                System.out.println("message: " + message);
            }

            @Override
            public void stateChanged(CuratorFramework client, ConnectionState newState) {

            }
        };

        //序列化
        QueueSerializer queueSerializer = new QueueSerializer() {
            @Override
            public byte[] serialize(String item) {
                return item.getBytes();
            }

            @Override
            public String deserialize(byte[] bytes) {
                return new String(bytes);
            }
        };

        //创建分布式队列
        QueueBuilder distributedBuilder = QueueBuilder.builder(client, queueConsumer, queueSerializer, lockPath);
        DistributedIdQueue distributedIdQueue = distributedBuilder.buildIdQueue();
        distributedIdQueue.start();

        //生成线程池
        ExecutorService executor = Executors.newCachedThreadPool();
        //生产
        BiConsumer, String> putConsumer = (queue, item) -> {
            try {
                Callable call = () -> {
                    try {
                        //向队尾添加数据,同时指定id
                        queue.put(item, item);
                        System.out.println(Thread.currentThread() + "  put : "+ item);
                        //休眠后删除刚添加的item, 此时可能还没有被消费
                        TimeUnit.MILLISECONDS.sleep(new Random().nextInt(1000));
                        queue.remove(item);
                        System.out.println(Thread.currentThread() + "  remove : "+ item);
                    } catch (Exception e) {
                    }
                    return true;
                };
                executor.submit(call);
            } catch (Exception e) {
            }
        };

        //分布式队列测试(5个线程生产)
        System.out.println("5个并发线程生产,测试分布式队列");
        for (int i = 0; i < 5; i++) {
            putConsumer.accept(distributedIdQueue, "item"+i);
        }

        executor.shutdown();
        TimeUnit.SECONDS.sleep(3);
        distributedIdQueue.close();
        client.close();
    }
}
输出:

5个并发线程生产,测试分布式队列
Thread[pool-4-thread-2,5,main]  put : item1
Thread[pool-4-thread-5,5,main]  put : item4
Thread[pool-4-thread-4,5,main]  put : item3
Thread[pool-4-thread-3,5,main]  put : item2
Thread[pool-4-thread-1,5,main]  put : item0
message: item1
Thread[pool-4-thread-1,5,main]  remove : item0
message: item4
message: item3
message: item2
Thread[pool-4-thread-2,5,main]  remove : item1
Thread[pool-4-thread-3,5,main]  remove : item2
Thread[pool-4-thread-4,5,main]  remove : item3
Thread[pool-4-thread-5,5,main]  remove : item4

六、带优先级的分布式队列DistributedPriorityQueue

带优先级的分布式队列DistributedPriorityQueue,可指定数据优先级,优先消费值小的数据。

示例代码:

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.queue.DistributedPriorityQueue;
import org.apache.curator.framework.recipes.queue.QueueBuilder;
import org.apache.curator.framework.recipes.queue.QueueConsumer;
import org.apache.curator.framework.recipes.queue.QueueSerializer;
import org.apache.curator.framework.state.ConnectionState;
import org.apache.curator.retry.ExponentialBackoffRetry;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;

public class ZookeeperDistributedPriorityQueueMain {
    public static void main(String[] args) throws Exception {
        //创建zookeeper客户端
        CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", new ExponentialBackoffRetry(1000, 3));
        client.start();

        //指定锁路径
        String lockPath = "/zkLockRoot/lock_21";

        //消费者
        QueueConsumer queueConsumer = new QueueConsumer() {
            @Override
            public void consumeMessage(String message) throws Exception {
                System.out.println("message: " + message);
            }

            @Override
            public void stateChanged(CuratorFramework client, ConnectionState newState) {

            }
        };

        //序列化
        QueueSerializer queueSerializer = new QueueSerializer() {
            @Override
            public byte[] serialize(String item) {
                return item.getBytes();
            }

            @Override
            public String deserialize(byte[] bytes) {
                return new String(bytes);
            }
        };

        //创建分布式队列
        QueueBuilder distributedBuilder = QueueBuilder.builder(client, queueConsumer, queueSerializer, lockPath);
        DistributedPriorityQueue distributedIdQueue = distributedBuilder.buildPriorityQueue(0);
        distributedIdQueue.start();

        //生成线程池
        ExecutorService executor = Executors.newCachedThreadPool();
        //生产
        BiConsumer, Integer> putConsumer = (queue, priority) -> {
            try {
                Callable call = () -> {
                    try {
                        queue.put("item"+priority, priority);
                        System.out.println(Thread.currentThread() + "  put : "+ "item"+priority);
                    } catch (Exception e) {
                    }
                    return true;
                };
                executor.submit(call);
            } catch (Exception e) {
            }
        };

        //分布式队列测试(5个线程生产)
        System.out.println("5个并发线程生产,测试分布式队列");
        for (int i = 0; i < 5; i++) {
            //随机指定优先级
            putConsumer.accept(distributedIdQueue, (int) (Math.random()*100));
        }

        executor.shutdown();
        TimeUnit.SECONDS.sleep(3);
        distributedIdQueue.close();
        client.close();
    }
}
输出:

5个并发线程生产,测试分布式队列
Thread[pool-4-thread-4,5,main]  put : item24
Thread[pool-4-thread-1,5,main]  put : item46
Thread[pool-4-thread-2,5,main]  put : item86
Thread[pool-4-thread-3,5,main]  put : item51
Thread[pool-4-thread-5,5,main]  put : item46
message: item24
message: item46
message: item46
message: item51
message: item86

你可能感兴趣的:(分布式处理)