• 分布式共享锁的程序逻辑流程


    有时根据需求,几台服务器需要从一个WEB接口或者数据库获得同样的资源,因为不能同时获取,就涉及到了资源调度算法

    一种资源调度逻辑是:

    1.程序节点启动时到zookeeper上注册一个“临时+序号”的znode,并监听父节点。

    2.获取父节点下所有的程序子节点,比较序号的大小。

    3.序号最小的获取到“锁”,去访问资源,访问完后,删除自己的节点,相当于释放锁,并且重新注册一个新的子节点。

    4.其他程序节点会收到事件通知,则可以去zk上获取锁。

    上伪代码:

    //getConnect()  获取连接
    //registerLock(/lock/app.emphemeral_sequential)   注册锁
    //getLock(){获取子节点;比较自己的序号是否是最小的,如果是,则返回锁获取成功}
    //访问资源
    //releaseLock(){删除自己的子节点,并创建一个新的子节点}
    
    //监听器
    process(){getLock(0}

    上源代码:

    public class DistributedClientLock {
        
    
        // 会话超时
        private static final int SESSION_TIMEOUT = 2000;
        // zookeeper集群地址
        private String hosts = "mini1:2181,mini2:2181,mini3:2181";
        private String groupNode = "locks";
        private String subNode = "sub";
        private boolean haveLock = false;
    
        private ZooKeeper zk;
        // 记录自己创建的子节点路径
        private volatile String thisPath;
    
        /**
         * 连接zookeeper
         */
        public void connectZookeeper() throws Exception {
            zk = new ZooKeeper(hosts, SESSION_TIMEOUT, new Watcher() {
                public void process(WatchedEvent event) {
                    try {
    
                        // 判断事件类型,此处只处理子节点变化事件
                        if (event.getType() == EventType.NodeChildrenChanged && event.getPath().equals("/" + groupNode)) {
                            //获取子节点,并对父节点进行监听
                            List<String> childrenNodes = zk.getChildren("/" + groupNode, true);
                            String thisNode = thisPath.substring(("/" + groupNode + "/").length());
                            // 去比较是否自己是最小id
                            Collections.sort(childrenNodes);
                            if (childrenNodes.indexOf(thisNode) == 0) {
                                //访问共享资源处理业务,并且在处理完成之后删除锁
                                doSomething();
                                
                                //重新注册一把新的锁
                                thisPath = zk.create("/" + groupNode + "/" + subNode, null, Ids.OPEN_ACL_UNSAFE,
                                        CreateMode.EPHEMERAL_SEQUENTIAL);
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
    
            // 1、程序一进来就先注册一把锁到zk上
            thisPath = zk.create("/" + groupNode + "/" + subNode, null, Ids.OPEN_ACL_UNSAFE,
                    CreateMode.EPHEMERAL_SEQUENTIAL);
    
            // wait一小会,便于观察
            Thread.sleep(new Random().nextInt(1000));
    
            // 从zk的锁父目录下,获取所有子节点,并且注册对父节点的监听
            List<String> childrenNodes = zk.getChildren("/" + groupNode, true);
    
            //如果争抢资源的程序就只有自己,则可以直接去访问共享资源 
            if (childrenNodes.size() == 1) {
                doSomething();
                thisPath = zk.create("/" + groupNode + "/" + subNode, null, Ids.OPEN_ACL_UNSAFE,
                        CreateMode.EPHEMERAL_SEQUENTIAL);
            }
        }
    
        /**
         * 处理业务逻辑,并且在最后释放锁
         */
        private void doSomething() throws Exception {
            try {
                System.out.println("gain lock: " + thisPath);
                Thread.sleep(2000);
                // do something
            } finally {
                System.out.println("finished: " + thisPath);
                
                zk.delete(this.thisPath, -1);
            }
        }
    
        public static void main(String[] args) throws Exception {
            DistributedClientLock dl = new DistributedClientLock();
            dl.connectZookeeper();
            Thread.sleep(Long.MAX_VALUE);
        }
    
        
    }
  • 相关阅读:
    鬼斧神工:求n维球的体积
    一个双曲函数的积分
    复杂的对数积分(八)
    一个有意思的对数积分的一般形式
    Logarithmic-Trigonometric积分系列(二)
    Logarithmic-Trigonometric积分系列(一)
    Some series and integrals involving the Riemann zeta function binomial coefficients and the harmonic numbers
    Euler Sums系列(六)
    Euler Sums系列(五)
    级数欣赏
  • 原文地址:https://www.cnblogs.com/fjlcoding/p/10058922.html
Copyright © 2020-2023  润新知