分布式锁,主要得益于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释放了排他锁

- 共享锁:Share Locks,简称S锁,又称为读锁
如果事务T1对数据对象T0加上了共享锁,那么T1只能对T0进行读操作,其他事务也能同时对T0加共享锁(不能是排他锁),直到T0上的所有共享锁都释放后T0才能被加排他锁

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