淺談Java基于Consul創(chuàng)建分布式鎖
Consul
Consul是HashiCorp公司推出的開源工具,用于實(shí)現(xiàn)分布式系統(tǒng)的服務(wù)發(fā)現(xiàn)與配置。
Consul是分布式的、高可用的、可橫向擴(kuò)展的。它具備以下特性 :
- 服務(wù)發(fā)現(xiàn):consul通過DNS或者HTTP接口使服務(wù)注冊和服務(wù)發(fā)現(xiàn)變的很容易。
- 健康檢查:健康檢測使consul可以快速的告警在集群中的操作。
- 鍵/值存儲(chǔ):一個(gè)用來存儲(chǔ)動(dòng)態(tài)配置的系統(tǒng)。提供簡單的HTTP接口,可以在任何地方操作。
- 多數(shù)據(jù)中心:無需復(fù)雜的配置,即可支持任意數(shù)量的區(qū)域。
一句話概況:Consul既可以用于注冊中心和配置中心,也可以做keyValue存儲(chǔ)。使用Consul做分布式鎖的底層原理就是keyValue存儲(chǔ)。
基于consul的分布式鎖
ConsulClient 是一個(gè)比較核心的類(consul客戶端),keyvalue存儲(chǔ)要用。
private ConsulClient consulClient;
@PostConstruct
public void init(){
consulClient = new ConsulClient(consulLockConfig.getHost(),consulLockConfig.getPort());
}createSession方法用于創(chuàng)建一個(gè)會(huì)話并返回sessionId,ttl是過期時(shí)間。我們在釋放鎖的時(shí)候會(huì)用到這個(gè)sessionId。
/**
* 創(chuàng)建一個(gè)sessionId
* @param lockName
* @param ttlSeconds
* @return
*/
private String createSession(String lockName,int ttlSeconds){
NewSession session = new NewSession();
//session.setBehavior(Session.Behavior.DELETE);
session.setBehavior(Session.Behavior.RELEASE);
session.setName("session " + lockName);
session.setTtl(ttlSeconds + "s");
return consulClient.sessionCreate(session, null).getValue();
}加鎖的實(shí)現(xiàn):
/**
* 獲取鎖
* @param lockName 鎖的名稱(key)
* @param ttlSeconds 鎖的超時(shí)時(shí)間
* @return
*/
private boolean tryLock(String lockName,int ttlSeconds){
try {
PutParams putParams = new PutParams();
String sessionId = createSession(lockName, ttlSeconds);
SessionIdHolder.setSessionId(sessionId);
log.info("consul加鎖開始(線程:{},鎖名稱:{},sessionId:{})",Thread.currentThread().getName(), lockName,sessionId);
putParams.setAcquireSession(sessionId);
//2.將構(gòu)件好的LockContext存儲(chǔ)在consul中
String key = consulLockConfig.PREFIX+lockName;
//加鎖成功
Boolean value = consulClient.setKVValue(key, sessionId, putParams).getValue();
if(value){
//開起一個(gè)新的線程去執(zhí)行鎖續(xù)命--調(diào)用看門狗的方式實(shí)現(xiàn)
if(consulLockConfig.isRenewal()){ //如果續(xù)期
new ConsulWatchDog(consulClient).watchSession(sessionId,ttlSeconds);//啟動(dòng)看門狗
}
log.info("consul加鎖成功(線程:{},鎖名稱:{},sessionId:{})",Thread.currentThread().getName(), lockName,sessionId);
return true;
}else{
//將sessionId刪除
//consulClient.deleteKVValue(key);
log.info("consul加鎖失敗(線程:{},鎖名稱:{},sessionId:{})",Thread.currentThread().getName(), lockName,sessionId);
return false;
}
}catch (Exception e){
e.printStackTrace();
return false;
}
}解鎖的實(shí)現(xiàn):
/**
* 釋放鎖
*/
public boolean unLock(String lockName){
//log.info("consul釋放鎖開始(線程:{},鎖名稱:{})",Thread.currentThread().getName(),lockName);
String sessionId = SessionIdHolder.getSessionId();
try {
//先根據(jù)鎖名稱找到對應(yīng)的sessionId session 是需要進(jìn)行存儲(chǔ)的 現(xiàn)在我們是通過一個(gè)lockContnt 假如說業(yè)務(wù)上不在一個(gè)微服務(wù)里釋放鎖 對應(yīng)的 其他微服務(wù)如何獲取到這把鎖呢
String key = consulLockConfig.PREFIX+lockName;
Response<GetValue> kvValue = consulClient.getKVValue(key);
if(kvValue==null) return false;
GetValue value = kvValue.getValue();
if(value==null) return false;
//log.info("consul釋放鎖開始(線程:{},鎖名稱:{},sessionId:{})",Thread.currentThread().getName(),lockName,sessionId);
PutParams putParams = new PutParams();
putParams.setReleaseSession(sessionId);
consulClient.setKVValue(key, sessionId, putParams);
//String sessionId = value.getDecodedValue();
consulClient.sessionDestroy(sessionId, null);// key value也會(huì)被刪除 是使用的DELETE
//刪除對應(yīng)的 sessionId存儲(chǔ)
//consulClient.deleteKVValue(key);
log.info("consul釋放鎖成功(線程:{},鎖名稱:{},sessionId:{})",Thread.currentThread().getName(),lockName,sessionId);
return true;
}catch (Exception e){
e.printStackTrace();
log.info("consul釋放鎖出錯(cuò)(線程:{},鎖名稱:{},sessionId:{})",Thread.currentThread().getName(),lockName,sessionId);
return false;
}
}到此這篇關(guān)于淺談Java基于Consul創(chuàng)建分布鎖的文章就介紹到這了,更多相關(guān)Consul創(chuàng)建分布鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Elasticsearch8.1中的Script使用實(shí)例深入解讀
這篇文章主要為大家介紹了Elasticsearch8.1中的Script使用實(shí)例深入解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10
Java實(shí)現(xiàn)Socket的TCP傳輸實(shí)例
這篇文章主要介紹了Java實(shí)現(xiàn)Socket的TCP傳輸,實(shí)例分析了java通過socket實(shí)現(xiàn)TCP傳輸?shù)南嚓P(guān)技巧,需要的朋友可以參考下2015-05-05
Java8中的LocalDateTime你會(huì)使用了嗎
LocalDateTime?是?Java?8?中日期時(shí)間?API?提供的一個(gè)類,在日期和時(shí)間的表示上提供了更加豐富和靈活的支持,本文就來講講LocalDateTime的一些具體使用方法吧2023-05-05
SpringBoot自動(dòng)配置深入探究實(shí)現(xiàn)原理
在springboot的啟動(dòng)類中可以看到@SpringBootApplication注解,它是SpringBoot的核心注解,也是一個(gè)組合注解。其中@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三個(gè)注解尤為重要。今天我們就來淺析這三個(gè)注解的含義2022-08-08
java多線程累加計(jì)數(shù)的實(shí)現(xiàn)方法
在多線程協(xié)作任務(wù)中,如何計(jì)算也是很重的,這篇文章主要介紹了java多線程累加計(jì)數(shù)的實(shí)現(xiàn)方法,感興趣的朋友可以了解一下2021-05-05
Javaweb使用thymeleaf局部刷新結(jié)合Layui插件實(shí)現(xiàn)Html分頁
本文主要介紹了Javaweb使用thymeleaf局部刷新結(jié)合Layui插件實(shí)現(xiàn)Html分頁,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10

