Zookeeper之分布式锁

来源:互联网 发布:linux中ping命令 编辑:程序博客网 时间:2024/06/09 05:42

Step 1:

private int threadId;    private ZooKeeper zk = null;    private String selfPath;    private String waitPath;    private String LOG_PREFIX_OF_THREAD;    private static final int SESSION_TIMEOUT = 10000;    private static final String GROUP_PATH = "/disLocks";    private static final String SUB_PATH = "/disLocks/sub";    private static final String CONNECTION_STRING = "192.168.*.*:2181";    private static final int THREAD_NUM = 10;     //确保连接zk成功;    private CountDownLatch connectedSemaphore = new CountDownLatch(1);    //确保所有线程运行结束;    private static final CountDownLatch threadSemaphore = new CountDownLatch(THREAD_NUM);    private static final Logger LOG = LoggerFactory.getLogger(DistributedLock.class);    public DistributedLock(int id) {        this.threadId = id;        LOG_PREFIX_OF_THREAD = "【第"+threadId+"个线程】";    }

Step 2:
获取锁

  /**     * 获取锁     * @return     */    private void getLock() throws KeeperException, InterruptedException {        selfPath = zk.create(SUB_PATH,null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);        LOG.info(LOG_PREFIX_OF_THREAD+"创建锁路径:"+selfPath);        if(checkMinPath()){            getLockSuccess();        }    }

Step 3:
创建节点

/**     * 创建节点     * @param path 节点path     * @param data 初始数据内容     * @return     */    public boolean createPath( String path, String data, boolean needWatch) throws KeeperException, InterruptedException {        if(zk.exists(path, needWatch)==null){            LOG.info( LOG_PREFIX_OF_THREAD + "节点创建成功, Path: "                    + this.zk.create( path,                    data.getBytes(),                    ZooDefs.Ids.OPEN_ACL_UNSAFE,                    CreateMode.PERSISTENT )                    + ", content: " + data );        }        return true;    }

Step 4:
创建Zookeeper连接

/**     * 创建ZK连接     * @param connectString  ZK服务器地址列表     * @param sessionTimeout Session超时时间     */    public void createConnection( String connectString, int sessionTimeout ) throws IOException, InterruptedException {            zk = new ZooKeeper( connectString, sessionTimeout, this);            connectedSemaphore.await();    }

Step 5:
成功获取锁

   /**     * 获取锁成功    */    public void getLockSuccess() throws KeeperException, InterruptedException {        if(zk.exists(this.selfPath,false) == null){            LOG.error(LOG_PREFIX_OF_THREAD+"本节点已不在了...");            return;        }        LOG.info(LOG_PREFIX_OF_THREAD + "获取锁成功,赶紧干活!");        Thread.sleep(2000);        LOG.info(LOG_PREFIX_OF_THREAD + "删除本节点:"+selfPath);        zk.delete(this.selfPath, -1);        releaseConnection();        threadSemaphore.countDown();    }

Step 6:
关闭连接

  /**     * 关闭ZK连接     */    public void releaseConnection() {        if ( this.zk !=null ) {            try {                this.zk.close();            } catch ( InterruptedException e ) {}        }        LOG.info(LOG_PREFIX_OF_THREAD + "释放连接");    }

Step 7:
检查自己是不是最小的节点

 /**     * 检查自己是不是最小的节点     * @return     */    public boolean checkMinPath() throws KeeperException, InterruptedException {         List<String> subNodes = zk.getChildren(GROUP_PATH, false);         Collections.sort(subNodes);         int index = subNodes.indexOf( selfPath.substring(GROUP_PATH.length()+1));         switch (index){             case -1:{                 LOG.error(LOG_PREFIX_OF_THREAD+"本节点已不在了..."+selfPath);                 return false;             }             case 0:{                 LOG.info(LOG_PREFIX_OF_THREAD+"子节点中,我果然是老大"+selfPath);                 return true;             }             default:{                 this.waitPath = GROUP_PATH +"/"+ subNodes.get(index - 1);                 LOG.info(LOG_PREFIX_OF_THREAD+"获取子节点中,排在我前面的"+waitPath);                 try{                     zk.getData(waitPath, true, new Stat());                     return false;                 }catch(KeeperException e){                     if(zk.exists(waitPath,false) == null){                         LOG.info(LOG_PREFIX_OF_THREAD+"子节点中,排在我前面的"+waitPath+"已失踪,幸福来得太突然?");                         return checkMinPath();                     }else{                         throw e;                     }                 }             }         }    }

Step 8:

    @Override    public void process(WatchedEvent event) {        if(event == null){            return;        }        Event.KeeperState keeperState = event.getState();        Event.EventType eventType = event.getType();        if ( Event.KeeperState.SyncConnected == keeperState) {            if ( Event.EventType.None == eventType ) {                LOG.info( LOG_PREFIX_OF_THREAD + "成功连接上ZK服务器" );                connectedSemaphore.countDown();            }else if (event.getType() == Event.EventType.NodeDeleted && event.getPath().equals(waitPath)) {                LOG.info(LOG_PREFIX_OF_THREAD + "收到情报,排我前面的家伙已挂,我是不是可以出山了?");                try {                    if(checkMinPath()){                        getLockSuccess();                    }                } catch (KeeperException e) {                    e.printStackTrace();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }else if ( Event.KeeperState.Disconnected == keeperState ) {            LOG.info( LOG_PREFIX_OF_THREAD + "与ZK服务器断开连接" );        } else if ( Event.KeeperState.AuthFailed == keeperState ) {            LOG.info( LOG_PREFIX_OF_THREAD + "权限检查失败" );        } else if ( Event.KeeperState.Expired == keeperState ) {            LOG.info( LOG_PREFIX_OF_THREAD + "会话失效" );        }    }