为什么用Zk实现分布式锁?
因为ZK自身的机制,创建节点的四种种类和每个节点的唯一性,使它适用于做分布式锁。
ZK分布式锁的羊群效应
所有的客户端都尝试去创建一个临时节点,但是只会有一个创建成功,其他的客户端去监听这个节点的变化。一旦这个临时节点释放,zk会通知监听这些节点的客户端,由于监听这个节点的数量多,会来回造成大量的网络开销,影响ZK的性能。这就是所谓的zk的分布式锁的羊群效应,这种方法是不可取的。
最理想的状态是什么?肯定是一个节点的变化去通知一个节点,所以,为了解决羊群效应的,所有的客户端去创建一个临时节点的时候,每个客户端都去创建一个临时顺序节点,大的节点监听比自己小的节点的变化。最小的节点先获得锁,操作完成释放锁,然后通知监听自己的节点去获取锁,依次类推。这样就可以解决羊群效应。
我们用Curator这个开源框架实现ZK的分布式锁。
先引入Curator包。
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.9.0</version>
</dependency>
共享资源:
public class Phone {
private int number = 5;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
//订购
public static void buy(Phone phone){
System.out.println("【" + Thread.currentThread().getName() + "】开始抢购");
//获取剩余手机数量
int currentNumber = phone.getNumber();
if (currentNumber <= 0){
System.out.println("抢购已结束,下次再来吧");
phone.setNumber(-1);
}else {
System.out.println("剩余手机数量:"+currentNumber+"个!");
currentNumber--;
phone.setNumber(currentNumber);
System.out.println("【" + Thread.currentThread().getName() + "】开始抢购");
}
System.out.println("------------------------------------------------------");
}
//支付
public static void pay(){
System.out.println("【" + Thread.currentThread().getName() + "】开始付款");
System.out.println("【" + Thread.currentThread().getName() + "】付款完成");
System.out.println("*****************************************************");
}
}
分布式锁代码的实现
public static void buyPhone(){
Phone phone = new Phone();
//可重入锁
InterProcessMutex interProcessMutex = new InterProcessMutex(zkClient,"/buy_phone");
for(int i= 0;i<100;i++){
new Thread(()->{
try{
//增加第一把锁
interProcessMutex.acquire();
System.out.println(Thread.currentThread().getName() + "获得第一把锁");
//完成抢购
Phone.buy(phone);
if(phone.getNumber()>=0){
interProcessMutex.acquire();
System.out.println(Thread.currentThread().getName() + "获得第二把锁");
//完成付款
Phone.pay();
}
}catch (Exception e){
e.printStackTrace();
}finally {
try{
interProcessMutex.release();
if(phone.getNumber()>=0){
interProcessMutex.release();
}
}catch (Exception e){
e.printStackTrace();
}
}
}).start();
}
}
来源:CSDN
作者:背着电脑旅行
链接:https://blog.csdn.net/qq_33628614/article/details/103408543