Zookeeper基础(五):分布式锁

分布式锁,主要得益于Zookeeper为我们保证了数据的强一致性

1、锁服务可分为两类,一类是保持独占,一类是控制时序

  • 保持独占,就是所有试图来获取这个锁的客户端,最终只有一个可以成功获得这把锁,通常的做法是把zk上的一个znode节点看做是一把锁,通过create znode的方式来实现,所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁;

  • 控制时序,就是所有试图来获取这个锁的客户端,最终都是会被安排执行,只是有个全局时序了;做法和上面基本类似,只是这里 /distribute_lock 已经预先存在,客户端在它下面创建临时有序节点(这个可以通过节点的属性控制:CreateMode.EPHEMERAL_SEQUENTIAL来指定);Zk的父节点(/distribute_lock)维持一份sequence,保证子节点创建的时序性,从而也形成了每个客户端的全局时序

2、分布式锁

  • 排他锁:Exclusive Locks,简称X锁,又称为写锁
    如果事务T1对数据对象T0加上了排他锁,那么在整个加锁期间,只允许事务T1对T0进行读取和更新操作,其他任何事务都不能在对这个数据对象进行任何类型的操作(不能再对该对象加锁),知道T1释放了排他锁
image.png
  • 共享锁:Share Locks,简称S锁,又称为读锁
    如果事务T1对数据对象T0加上了共享锁,那么T1只能对T0进行读操作,其他事务也能同时对T0加共享锁(不能是排他锁),直到T0上的所有共享锁都释放后T0才能被加排他锁
image.png

3、Curator分布式锁

Curator实现了以下各种类型的分布式锁:

  • InterProcessMutex 全局可重入锁
    客户端都可以请求锁,并且同一个客户端在拥有锁的同时,可以多次过去锁,不会被阻塞

  • InterProcessSemaphoreMutex 不可重入锁
    不能在同一个线程(客户端)中重入

  • InterProcessReadWriteLock 可重入读写锁
    一个读写锁管理一对相关的锁,一个负责读操作,一个负责写操作,读操作在写锁没被使用时,可同时由多个进程使用;而写锁使用时,不允许读(阻塞)
    可重入读写锁,是可重入的,一个拥有写锁的线程可重入读锁,但是读锁却不能重入写锁;这其实意味着,写锁可以降级为读锁,比如请求写锁——》请求读锁——》释放写锁(同一个线程操作);而读锁是不能升级成写锁的

  • InterProcessSemaphoreV2 信号量

  • InterProcessMultiLock 多锁对象
    InterProcessMultiLock 是一个锁的容器,当调用acquire时,所有的锁都会被acquire,如果请求失败,所有的锁都会被release;同样调用release时,所有的锁都会被release,如果请求失败,则忽略。
    基本上他就是组锁的代表,在它上面的请求释放操作,都会百传递给他包含的所有的锁

4、InterProcessMutex Demo

package com.xxx.api.curator.lock;

import com.xxx.ZookeeperUtil;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;

public class CuratorInterProcessMutex {
    RetryPolicy retryPolicy = new ExponentialBackoffRetry(2000, 5);//重试策略
    //工厂创建连接
    CuratorFramework   cf= CuratorFrameworkFactory.builder()
            .connectString(ZookeeperUtil.connectString)
            .sessionTimeoutMs(ZookeeperUtil.sessionTimeout)
            .retryPolicy(retryPolicy)
            .build();

     InterProcessMutex lock;
    public CuratorInterProcessMutex(String path) {
        lock=new InterProcessMutex(cf, path);
        cf.start();//链接
    }

    /***
     * 获取资源
     * @see org.apache.curator.framework.recipes.locks.LockInternals
     * @throws Exception
     */
    public void acquire() throws Exception {
        lock.acquire();
    }

    /****
     * 释放资源
     * @throws Exception
     */
    public void release() throws Exception {
        lock.release();
    }
}
package com.xxx.api.curator.lock;
import com.xxx.ZookeeperUtil;
import com.xxx.lock.DistributedLock;

public class LockTest implements  Runnable {
    static  int i=0;
    CuratorInterProcessMutex curatorInterProcessMutex=new CuratorInterProcessMutex("/root");

    @Override
    public void run() {
        try {
            curatorInterProcessMutex.acquire();
            for(int j=0;j<1000000;j++){
                i++;
            }
            curatorInterProcessMutex.release();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) throws InterruptedException {
        LockTest lockTest=new LockTest();
        Thread thread=new Thread(lockTest);
        Thread thread2=new Thread(lockTest);
        thread.start();thread2.start();
        thread.join();thread2.join();
        System.out.println(i);
    }
}

Zookeeper

你可能感兴趣的:(Zookeeper基础(五):分布式锁)