Zookeeper 4 Zookeeper JavaAPI 操作 4.9 模拟12306 售票案例
Zookeeper
【黑马程序员Zookeeper视频教程,快速入门zookeeper技术】
文章目录
- Zookeeper
- 4 Zookeeper JavaAPI 操作
- 4.9 模拟12306 售票案例
- 4.9.1 Curator 实现分布式锁 API
- 4.9.2 分布式锁案例 - 模拟12306 售票
4 Zookeeper JavaAPI 操作
4.9 模拟12306 售票案例
4.9.1 Curator 实现分布式锁 API
在Curator中有五种锁方案:
- InterProcessSemaphoreMutex:分布式排它锁(非可重入锁)
- InterProcessMutex:分布式可重入排它锁
- InterProcessReadWriteLock:分布式读写锁
- InterProcessMultiLock:将多个锁作为单个实体管理的容器
- InterProcessSemaphoreV2:共享信号量
4.9.2 分布式锁案例 - 模拟12306 售票
平时我们 用这些,它们其实都不是 真正出票 的,它们只是代理商
12306 才是真正的出票 的
12306 不多解释,那个请求量,单机…,肯定会搭 集群的
代理商访问 12306, 然后12306 访问自己的 数据库【当然数据库 也会做成集群,对外访问接口一个】
资源在谁那儿,分布式锁 就加到 谁那儿,所以肯定是在 12306 上加
引入Zookeeper 后,12306 就可以作为 Zookeeper 的客户端 【分布式锁 由Zookeeper 提供】
【简单模拟】
先来一个票类
package com.dingjiaxiong.curator;
/**
* ClassName: Ticket12306
* date: 2022/11/15 15:18
*
* @author DingJiaxiong
*/
public class Ticket12306 implements Runnable{
private int tickets = 10; //数据库的票数
@Override
public void run() {
//一直对外提供服务
while (true){
if (tickets > 0){
System.out.println(Thread.currentThread() + ":" + tickets);
tickets --;
}
}
}
}
来一个 新的测试类
package com.dingjiaxiong.curator;
/**
* ClassName: LockTest
* date: 2022/11/15 15:17
*
* @author DingJiaxiong
*/
public class LockTest {
public static void main(String[] args) {
Ticket12306 ticket12306 = new Ticket12306();
//创建客户端【买票的】
Thread t1 = new Thread(ticket12306,"携程");
Thread t2 = new Thread(ticket12306,"飞猪");
t1.start();
t2.start();
}
}
现在直接运行就会 产生 并发问题,看看结果
很明显这样是不行的
【现在就给 它加上分布式 锁】
package com.dingjiaxiong.curator;
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;
import java.util.concurrent.TimeUnit;
/**
* ClassName: Ticket12306
* date: 2022/11/15 15:18
*
* @author DingJiaxiong
*/
public class Ticket12306 implements Runnable {
private int tickets = 10; //数据库的票数
private InterProcessMutex lock;
public Ticket12306() {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000, 10);
CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString("zookeeper的IP :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);
tickets--;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 释放锁
try {
lock.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
OK,直接重新运行测试类
这下就不会 冲了
看看命令行 客户端
多看几次
就是我们 之前说的 使用临时顺序节点实现的东西
【那就这样吧】