Zookeeper 分布式锁
分布式锁:用来处理 跨机器的进程之间,数据同步问题。
应用是在分布式群集的情况下,属于多JVM的工作环境,跨JVM之间是无法使用多线程的锁解决同步问题。
Zookeeper实现分布式锁的原理
•核心思想:当客户端要获取锁,则创建节点,使用完锁,则删除该节点。
1.客户端获取锁时,在lock节点下创建临时顺序节点。
2.然后获取lock下面的所有子节点,客户端获取到所有的子节点之后,如果发现自己创建的子节点序号最小,那么就认为该客户端获取到了锁。使用完锁后,将该节点删除。
3.如果发现自己创建的节点并非lock所有子节点中最小的,说明自己还没有获取到锁,此时客户端需要找到比自己小的那个节点,同时对其注册事件监听器,监听删除事件。
4.如果发现比自己小的那个节点被删除,则客户端的
Watcher会收到相应通知,此时再次判断自己创建的节点
是否是lock子节点中序号最小的,如果是则获取到了锁,
如果不是则重复以上步骤继续获取到比自己小的一个节点
并注册监听。
练习代码
网络购票代码
Curator实现分布式锁API
-
在Curator中有五种锁方案:
-
InterProcessSemaphoreMutex:分布式排它锁(非可重入锁)
-
InterProcessMutex:分布式可重入排它锁
-
InterProcessReadWriteLock:分布式读写锁
-
InterProcessMultiLock:将多个锁作为单个实体管理的容器
-
InterProcessSemaphoreV2:共享信号量
-
**主方法类 调用线程实现类 开启线程 **
public class LockTest {
public static void main(String[] args) {
Ticket12306 tt = new Ticket12306();
// 创建客户端
Thread t1 = new Thread(tt, "京东");
Thread t2 = new Thread(tt, "完蛋");
t1.start();
t2.start();
}
}
线程实现类,实现 分布式锁
public class Ticket12306 implements Runnable{
private int tickets = 10; // 总票数
private InterProcessMutex lock;
public Ticket12306(){
//重试策略
RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000, 10);
//2.第二种方式
// 在为 创建 分布式锁对象的参数消费者对象时,不用写出指定的名称空间
// namespace("itheima")
//CuratorFrameworkFactory.builder();
CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString("192.168.23.130:2181")
.sessionTimeoutMs(60 * 1000)
.connectionTimeoutMs(15 * 1000)
.retryPolicy(retryPolicy)
.build();
//开启连接
client.start();
// 创建 分布式锁 参数 需要 消费者对象 与 节点路径
lock = new InterProcessMutex(client,"/lock");
}
@Override
public void run() {
while (true){
// 获取锁
try {
lock.acquire(3, TimeUnit.SECONDS);
if (tickets>0){
System.out.println(Thread.currentThread()+":"+tickets);
Thread.sleep(100);
tickets--;
}
} catch (Exception e) {
e.printStackTrace();
}finally {
// 释放锁
try {
lock.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}