zookeeper应用场景

订阅发布(配置中心)

watch机制
统一配置管理(disconf),一般有两种方式:pull和push,zookeeper使用的是两者相结合的方式,客户端向服务器端注册自己要关注的节点,一旦节点数据发生变化,那么服务器端向客户端发送watcher事件通知,客户端收到通知后,主动向服务器端获取最新的数据。
配置特点:数据量比较小、数据在运行时会发生动态变更、集群共享配置

分布式锁

1、redis:setnx,使用redis提供的命令实现
2、数据库:创建一个表,通过索引唯一的方式,比如一个表
create table(id,methodname…)在methodname增加唯一索引,多个应用访问统一节点时,先在表里insert一条数据,xxx,其他客户端再插入时,索引重复。当使用完后,delete掉。
mysql中的 for update可以行级锁,也称独占锁,效率比较低。
3、zookeeper:利用临时有序节点和watch机制
分布式锁是进程之间的控制
排它锁(写锁)
利用zookeeper同一目录下节点名称唯一性实现。
A、B、C同时往一个目录下写一个名称一样的临时接点,能创建成功的可以拿到锁。
共享锁(读锁)
利用有序临时节点,所有客户端往里面去写节点,每一个客户端写节点后,最小的节点有优先级去获取数据。通过顺序性去控制共享锁,共享锁里可以包含写和读。

package DistrubuteLock.javaapi;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;

import java.io.IOException;
import java.util.List;
import java.util.Random;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class DistrubuteLockDemo {

    private static final String ROOT_LOCKS="/LOCKS";
    private ZooKeeper zookeeper;
    private int sessionTimeOut;//回话超时时间
    private String lockId;  //记录节点id
    private static final byte[] data={1,2};
    private CountDownLatch countDownLatch = new CountDownLatch(1);

    public DistrubuteLockDemo() throws IOException, InterruptedException {
        this.zookeeper = ZookeeperClient.getInstance();
        this.sessionTimeOut = ZookeeperClient.getSessionTimeOut();
    }

    //获取锁的方法
    public boolean lock() throws KeeperException, InterruptedException {
        //每个客户端都会创建一个临时有序节点
        lockId = zookeeper.create(ROOT_LOCKS+"/",data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        System.out.println(Thread.currentThread().getName()+"成功创建了LOCK节点,节点ID为:["+lockId+"],开始去竞争锁。");
        List<String> childrenNodes = zookeeper.getChildren(ROOT_LOCKS,true);
        //从小到大排序
        SortedSet<String> sorted = new TreeSet<>();
        for (String children:childrenNodes) {
            sorted.add(children);
        }
        String first = sorted.first();
        if(lockId.equals(first)){
            //表示当前就是最下的,意味着获取锁了
            System.out.println(Thread.currentThread().getName()+"->成功获得锁,lock节点为:" +lockId);
            return true;
        }
        SortedSet<String> lessThenLockId = sorted.headSet(lockId);
        if(!lessThenLockId.isEmpty()){
            String preLockId = lessThenLockId.last();
            zookeeper.exists(preLockId,new LockWatcher(countDownLatch));
            countDownLatch.await(sessionTimeOut, TimeUnit.MICROSECONDS);
            //上面这段代码意味着回话超时,或者节点被删除,就可以获取锁
            System.out.println(Thread.currentThread().getName()+"成功获取锁,LOCKID:"+lockId);
            return  true;
        }
        return false;
    }

    //释放锁操作
    public boolean unlock() {
        System.out.println(Thread.currentThread().getName()+"->开始释放锁:["+lockId+"]");
        try {
            zookeeper.delete(lockId,-1);
            System.out.println("LOCKID:"+lockId+"成功释放。");
            return true;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (KeeperException e) {
            e.printStackTrace();
        }
        return false;
    }

    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(10);
        Random random = new Random();
        for (int i =0;i<10;i++){
            new Thread(()->{
                DistrubuteLockDemo lock = null;
                try {
                    lock = new DistrubuteLockDemo();
                    countDownLatch.countDown();
                    countDownLatch.await();
                    lock.lock();
                    Thread.sleep(random.nextInt(500));
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (KeeperException e) {
                    e.printStackTrace();
                }finally {
                    if(lock!=null){
                        lock.unlock();
                    }
                }
            }).start();
        }
    }
}

负载均衡

ID生成器

分布式队列

分布式队列:有先进先出、Barrier模式(围栏模式)。
先进先出
先进先出利用有序节点,和分布式锁原理一样,通过getChild获取节点下所有子元素,子节点就是要执行的任务,如果自己不是最小的节点,那么监控比自己小的上一个节点,否则处于等待。接收watch通知,重复该流程。
Barrier模式
在先进先出的基础上增加一个number作为触发条件。

统一命名服务

master选举

curator实现
LeaderLatch
写一个master
LeaderSelector
每一个应用写一个临时有序节点,根据最小节点来获取优先权

package MasterSlaveCurator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.leader.LeaderSelector;
import org.apache.curator.framework.recipes.leader.LeaderSelectorListenerAdapter;
import org.apache.curator.retry.ExponentialBackoffRetry;

import java.util.concurrent.TimeUnit;

public class MasterSlaveCurator {
    private final static String CONNECT_STRING = "192.168.36.128:2181,192.168.36.129:2181,192.168.36.130:2181";

    public static void main(String[] args) {
        CuratorFramework curatorFramework = CuratorFrameworkFactory.builder().connectString(CONNECT_STRING).
                retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();
        LeaderSelector leaderSelector = new LeaderSelector(curatorFramework, CONNECT_STRING, new LeaderSelectorListenerAdapter() {
            @Override
            public void takeLeadership(CuratorFramework curatorFramework) throws Exception {
                //获得leader成功
                TimeUnit.SECONDS.sleep(1);
            }
        });
        //自动选举
        leaderSelector.autoRequeue();//自动争抢
        leaderSelector.start();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值