分布式锁

流程
- 查看目标Node是否已经创建,已经创建,那么等待锁。
- 如果未创建,创建一个临时节点zkTemp,表示已经占有锁。
- 如果创建失败,那么证明锁已经被其他线程占有了,那么同样等待锁。
- 当释放锁,节点被删除,唤醒之前等待锁的线程去争抢锁。
分布式案例
OrderNumber生成订单号类:
/*生成订单号*/
public class OrderNumber {
private static int number=0;
//生成订单号
public String getOrderNumber(){
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
++number;
return simpleDateFormat.format(new Date())+"\t"+number;
}
}
OrderService订单业务逻辑类:
/*订单业务逻辑*/
public class OrderService implements Runnable {
private static OrderNumber orderNumber=new OrderNumber();
public Lock lock=new ZookeeperImpl();
//生成订单
public void getnumber(){
/*synchronized (orderNumber){
System.out.println("获取的订单编号为:"+orderNumber.getOrderNumber());
}*/
lock.getLock(); //获取锁
System.out.println("获取的订单编号为:"+orderNumber.getOrderNumber());
lock.unLock(); //释放锁
}
@Override
public void run() {
getnumber();
}
public static void main(String[] args) {
for (int i=0;i<100;i++){
new Thread(new OrderService()).start();
}
}
}
Lock接口类:
public interface Lock {
//获取锁
public void getLock();
//释放锁
public void unLock();
}
ZookeeperLock实现类:
public abstract class ZookeeperLock implements Lock {
//连接地址
private static final String CONNECT_ADDDR="0.0.0.0:2181";
protected ZkClient zkClient=new ZkClient(CONNECT_ADDDR);
//获取锁
@Override
public void getLock() {
if (tryLock()){
System.out.println("获取到锁资源");
}else{
//当返回值为false的时候,代表锁已经被占用,需等待锁
waitLock();
//等待之后需再次获取锁
getLock();
}
}
//释放锁
@Override
public void unLock() {
if (zkClient!=null){
zkClient.close();
}
}
//获取锁资源
public abstract boolean tryLock();
//等待
public abstract void waitLock();
}
ZookeeperImpl继承类:
/*真正获取锁和释放锁*/
public class ZookeeperImpl extends ZookeeperLock {
//信号量
private CountDownLatch countDownLatch=null;
//获取锁资源
@Override
public boolean tryLock() {
try {
zkClient.createEphemeral("/zkTemp");
return true;
}catch (Exception e){
return false;
}
}
//等待
@Override
public void waitLock() {
IZkDataListener iZkDataListener=new IZkDataListener() {
@Override
public void handleDataChange(String s, Object o) throws Exception {
}
@Override
public void handleDataDeleted(String s) throws Exception {
if (countDownLatch!=null){
//释放信号量
countDownLatch.countDown();
}
}
};
//如果节点已经存在 就等待
if (zkClient.exists("/zkTemp")){
countDownLatch=new CountDownLatch(1);
System.out.println("锁已经被占用 需要等待============================");
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
分布式锁思路
分布式锁使用zk,在zk上创建一个临时节点(有效期) ,使用临时节点作为锁,因为节点不允许重复。
如果能创建节点成功,生成订单号,如果创建节点失败,等待。临时节点zk关闭,释放锁,其他节点就可以重新生成订单号。

浙公网安备 33010602011771号