分布式锁
- 在我们进行单机应用开发,涉及并发同步的时候,我们往往采用synchronized或者Lock的方式来解决多线程间的代码同步问题,这时多线程的运行都是在同一个JVM之下,没有任何问题。
- 但当我们的应用是分布式集群工作的情况下,属于多JVM下的工作环境,跨JVM之间已经无法通过多线程的锁解决同步问题。
- 那么就需要一种更加高级的锁机制,来处理种跨机器的进程之间的数据同步问题——这就是分布式锁。
ZooKeeper分布式锁的原理
至于为什么是临时顺序节点是因为,临时节点在客户端与服务端断开连接后,自动删除临时节点,释放锁;创建临时节点主要是为了防止客户端发生宕机行为,然后一直把锁占有着,到时后面的客户端不能运行。
设置顺序节点则是因为客户端执行的先后顺序则是按照节点的大小顺序来的。
Curator实现分布式锁API
- 在Curator中有五种锁
- InterProcessSemaphoreMutex:分布式排它锁(非可重入锁)
- InterProcessMutex:分布式可重入排它锁
- InterProcessReadWriteLock:分布式读写锁
- InterProcessMultiLock:将多个锁作为单个实体管理的容器
- InterProcessSemaphoreV2:共享信号量
模拟卖票案例
线程类
**
* 多线程 模拟卖票
* 多线程的两种实现方式
* 方式1:继承Tread线程类
* 方式2:实现Runnable线程接口,重写run()方法
*/
public class Lock extends Thread {
private static CuratorFramework client;
static {
//连接重试策略
ExponentialBackoffRetry retry = new ExponentialBackoffRetry(3000, 10);
//建立客户端与服务器连接
client = CuratorFrameworkFactory.builder().connectString("192.168.242.130:2181")
.connectionTimeoutMs(15 * 1000)
.sessionTimeoutMs(1000 * 60)
.retryPolicy(retry).build();
//开启连接
client.start();
}
@Override
public void run() {
//使用curator提供的分布所来保证线程安全 分布式可重用排他锁
InterProcessMutex interProcessMutex = new InterProcessMutex(client, "/app2");
//定义票数
int i = 100;
//模拟卖票窗口一直开启
while (true) {
try {
//获取锁
interProcessMutex.acquire();
//当票数大于0的时候才能卖票
if (i > 0) {
System.out.println("第" + i + "张票已经卖出!");
//票数减1
i--;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//释放锁
try {
interProcessMutex.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
提示
一般使用版本号对比更新的操作是乐观锁