【一】介紹
分佈式鎖簡介:
1.1 什麼是鎖
在單機環境下,當存在多個線程可以同時改變某個共享變量時,就需要同步來實現該功能,使其線程安全。
而同步就是通過鎖來實現的。鎖保證了同一時刻只有一個線程來修改共享變量。
在單機環境下,Java提供了一些併發安全包可以一定程度上保證線程安全,但是在分佈式環境(多機環境)下,這些併發包顯得就無能爲力了!!
1.2 什麼是分佈式
分佈式的CAP理論:
任何一個分佈式系統都無法同時滿足一致性(Consistency)、可用性(Availability)和分區容錯性(Partition tolerance),最多隻能同時滿足兩項。
目前很多大型網站及應用都是分佈式部署的,分佈式場景中的數據一致性問題一直是一個比較重要的話題。基於 CAP理論,很多系統在設計之初就要對這三者做出取捨。在互聯網領域的絕大多數的場景中,都需要犧牲強一致性來換取系統的高可用性,系統往往只需要保證最終一致性。
3、什麼是分佈式鎖
顧名思義,分佈式鎖肯定是用在分佈式環境下。在分佈式環境下,使用分佈式鎖的目的也是保證同一時刻只有一個線程來修改共享變量,修改共享緩存……。
1.3 分佈式鎖特性
1、在分佈式系統環境下,一個方法在同一時間只能被一個機器的一個線程執行;
2、高可用的獲取鎖與釋放鎖;
3、高性能的獲取鎖與釋放鎖;
4、具備可重入特性;
5、具備鎖失效機制,防止死鎖;
6、具備非阻塞鎖特性,即沒有獲取到鎖將直接返回獲取鎖失敗
【二】curator介紹
- public void acquire();//獲取鎖
- public boolean acquire(long time, TimeUnit unit);//獲取鎖,可以指定阻塞時間
- public void release();//釋放鎖
- boolean isAcquiredInThisProcess();//判斷當前是否持有鎖,實際使用中,如果持有鎖,可以進行鎖的釋放
實現類:
InterProcessMultiLock 將多個鎖作爲單個實體管理的容器
InterProcessMutex 分佈式可重入排它鎖
InterProcessReadWriteLock 分佈式讀寫鎖
InterProcessSemaphoreMutex 分佈式排它鎖
InterProcessSemaphoreV2 信號量
【三】代碼實現
package com.provider.demo.comment;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
/**
* @Description
* @Author fengwen
* @Date 2020/1/22 18:12
* @Version V1.0
*/
public class DistributedLock {
public static Logger log = LoggerFactory.getLogger(DistributedLock.class);
//可重入排它鎖
private InterProcessMutex interProcessMutex;
//競爭資源標誌
private String lockName;
//根節點
private String root = "/distributed/lock/";
private static CuratorFramework curatorFramework;
private static String ZK_URL = "127.0.0.1:2181";
static{
curatorFramework= CuratorFrameworkFactory.newClient(ZK_URL,new ExponentialBackoffRetry(1000,3));
curatorFramework.start();
}
/**
* 實例化
* @param lockName
*/
public DistributedLock(String lockName){
try {
this.lockName = lockName;
interProcessMutex = new InterProcessMutex(curatorFramework, root + lockName);
}catch (Exception e){
log.error("initial InterProcessMutex exception="+e);
}
}
/**
* 獲取鎖
*/
public void acquireLock(){
try {
//重試2次,每次最大等待2s,也就是最大等待4s
while (true){
boolean acquire = interProcessMutex.acquire(2, TimeUnit.SECONDS);
if (acquire){
log.info("Thread:"+Thread.currentThread().getId()+" acquire distributed lock success");
break;
}
}
} catch (Exception e) {
log.error("distributed lock acquire exception="+e);
}
}
/**
* 釋放鎖
*/
public void releaseLock(){
try {
if(interProcessMutex != null && interProcessMutex.isAcquiredInThisProcess()){
interProcessMutex.release();
curatorFramework.delete().inBackground().forPath(root+lockName);
log.info("Thread:"+Thread.currentThread().getId()+" release distributed lock success");
}
}catch (Exception e){
log.info("Thread:"+Thread.currentThread().getId()+" release distributed lock exception="+e);
}
}
}