更新時(shí)間:2023-07-11 來(lái)源:黑馬程序員 瀏覽量:
Consul是HashiCorp公司推出的開源工具,用于實(shí)現(xiàn)分布式系統(tǒng)的服務(wù)發(fā)現(xiàn)與配置。 Consul是分布式的、高可用的、可橫向擴(kuò)展的。它具備以下特性 :
服務(wù)發(fā)現(xiàn):consul通過DNS或者HTTP接口使服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)變的很容易。 健康檢查:健康檢測(cè)使consul可以快速的告警在集群中的操作。 鍵/值存儲(chǔ):一個(gè)用來(lái)存儲(chǔ)動(dòng)態(tài)配置的系統(tǒng)。提供簡(jiǎn)單的HTTP接口,可以在任何地方操作。 多數(shù)據(jù)中心:無(wú)需復(fù)雜的配置,即可支持任意數(shù)量的區(qū)域。
一句話概況:Consul既可以用于注冊(cè)中心和配置中心,也可以做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í)間。我們?cè)卺尫沛i的時(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ù)鎖名稱找到對(duì)應(yīng)的sessionId session 是需要進(jìn)行存儲(chǔ)的 現(xiàn)在我們是通過一個(gè)lockContnt 假如說(shuō)業(yè)務(wù)上不在一個(gè)微服務(wù)里釋放鎖 對(duì)應(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 //刪除對(duì)應(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; } }
Java培訓(xùn):布隆過濾器與布谷鳥過濾器的區(qū)別及應(yīng)用場(chǎng)景
2023-07-11Java內(nèi)部培訓(xùn):有哪些避免空指針的方法?
2023-07-10業(yè)務(wù)開發(fā)時(shí),接口不能對(duì)外暴露怎么辦?
2023-07-10Java培訓(xùn):什么叫內(nèi)存溢出和內(nèi)存泄漏?
2023-07-07一鍵免費(fèi)學(xué)!黑馬程序員全新編程實(shí)戰(zhàn)項(xiàng)目《蒼穹外賣》發(fā)布!
2023-07-06Java虛擬機(jī)和Dalvik虛擬機(jī)有哪些區(qū)別和不同?
2023-07-06