1. 程式人生 > >【高併發】你知道嗎?大家都在使用Redisson實現分散式鎖了!!

【高併發】你知道嗎?大家都在使用Redisson實現分散式鎖了!!

寫在前面

忘記之前在哪個群裡有朋友在問:有出分散式鎖的文章嗎~@冰河?我的回答是:這週會有,也是【高併發】專題的。想了想,還是先發一個如何使用Redisson實現分散式鎖的文章吧?為啥?因為使用Redisson實現分散式鎖簡單啊!Redisson框架是基於Redis實現的分散式鎖,非常強大,只需要拿來使用就行了,至於分散式鎖的原理啥的,後面再擼一篇文章就是了。

Redisson框架十分強大,基於Redisson框架可以實現幾乎你能想到的所有型別的分散式鎖。這裡,我就列舉幾個型別的分散式鎖,並各自給出一個示例程式來加深大家的理解。有關分散式鎖的原理細節,後續專門擼一篇文章咱們慢慢聊!

1.可重入鎖(Reentrant Lock)

Redisson的分散式可重入鎖RLock Java物件實現了java.util.concurrent.locks.Lock介面,同時還支援自動過期解鎖。

public void testReentrantLock(RedissonClient redisson){
	RLock lock = redisson.getLock("anyLock");
	try{
		// 1. 最常見的使用方法
		//lock.lock();
		// 2. 支援過期解鎖功能,10秒鐘以後自動解鎖, 無需呼叫unlock方法手動解鎖
		//lock.lock(10, TimeUnit.SECONDS);
		// 3. 嘗試加鎖,最多等待3秒,上鎖以後10秒自動解鎖
		boolean res = lock.tryLock(3, 10, TimeUnit.SECONDS);
		if(res){ //成功
		// do your business
		}
	} catch (InterruptedException e) {
		e.printStackTrace();
	} finally {
		lock.unlock();
	}
}

Redisson同時還為分散式鎖提供了非同步執行的相關方法:

public void testAsyncReentrantLock(RedissonClient redisson){
	RLock lock = redisson.getLock("anyLock");
	try{
		lock.lockAsync();
		lock.lockAsync(10, TimeUnit.SECONDS);
		Future<Boolean> res = lock.tryLockAsync(3, 10, TimeUnit.SECONDS);
		if(res.get()){
		// do your business
		}
	} catch (InterruptedException e) {
		e.printStackTrace();
	} catch (ExecutionException e) {
		e.printStackTrace();
	} finally {
		lock.unlock();
	}
}

2.公平鎖(Fair Lock)

Redisson分散式可重入公平鎖也是實現了java.util.concurrent.locks.Lock介面的一種RLock物件。在提供了自動過期解鎖功能的同時,保證了當多個Redisson客戶端執行緒同時請求加鎖時,優先分配給先發出請求的執行緒。

public void testFairLock(RedissonClient redisson){
	RLock fairLock = redisson.getFairLock("anyLock");
	try{
		// 最常見的使用方法
		fairLock.lock();
		// 支援過期解鎖功能, 10秒鐘以後自動解鎖,無需呼叫unlock方法手動解鎖
		fairLock.lock(10, TimeUnit.SECONDS);
		// 嘗試加鎖,最多等待100秒,上鎖以後10秒自動解鎖
		boolean res = fairLock.tryLock(100, 10, TimeUnit.SECONDS);
	} catch (InterruptedException e) {
		e.printStackTrace();
	} finally {
		fairLock.unlock();
	}
}

Redisson同時還為分散式可重入公平鎖提供了非同步執行的相關方法:

RLock fairLock = redisson.getFairLock("anyLock");
fairLock.lockAsync();
fairLock.lockAsync(10, TimeUnit.SECONDS);
Future<Boolean> res = fairLock.tryLockAsync(100, 10, TimeUnit.SECONDS);

3.聯鎖(MultiLock)

Redisson的RedissonMultiLock物件可以將多個RLock物件關聯為一個聯鎖,每個RLock物件例項可以來自於不同的Redisson例項。

public void testMultiLock(RedissonClient redisson1,RedissonClient redisson2, RedissonClient redisson3){
	RLock lock1 = redisson1.getLock("lock1");
	RLock lock2 = redisson2.getLock("lock2");
	RLock lock3 = redisson3.getLock("lock3");
	RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
	try {
		// 同時加鎖:lock1 lock2 lock3, 所有的鎖都上鎖成功才算成功。
		lock.lock();
		// 嘗試加鎖,最多等待100秒,上鎖以後10秒自動解鎖
		boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
	} catch (InterruptedException e) {
		e.printStackTrace();
	} finally {
		lock.unlock();
	}
}

4.紅鎖(RedLock)

Redisson的RedissonRedLock物件實現了Redlock介紹的加鎖演算法。該物件也可以用來將多個RLock物件關聯為一個紅鎖,每個RLock物件例項可以來自於不同的Redisson例項。

public void testRedLock(RedissonClient redisson1,RedissonClient redisson2, RedissonClient redisson3){
	RLock lock1 = redisson1.getLock("lock1");
	RLock lock2 = redisson2.getLock("lock2");
	RLock lock3 = redisson3.getLock("lock3");
	RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
	try {
		// 同時加鎖:lock1 lock2 lock3, 紅鎖在大部分節點上加鎖成功就算成功。
		lock.lock();
		// 嘗試加鎖,最多等待100秒,上鎖以後10秒自動解鎖
		boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
	} catch (InterruptedException e) {
		e.printStackTrace();
	} finally {
		lock.unlock();
	}
}

5.讀寫鎖(ReadWriteLock)

Redisson的分散式可重入讀寫鎖RReadWriteLock,Java物件實現了java.util.concurrent.locks.ReadWriteLock介面。同時還支援自動過期解鎖。該物件允許同時有多個讀取鎖,但是最多隻能有一個寫入鎖。

RReadWriteLock rwlock = redisson.getLock("anyRWLock");
// 最常見的使用方法
rwlock.readLock().lock();
// 或
rwlock.writeLock().lock();
// 支援過期解鎖功能
// 10秒鐘以後自動解鎖
// 無需呼叫unlock方法手動解鎖
rwlock.readLock().lock(10, TimeUnit.SECONDS);
// 或
rwlock.writeLock().lock(10, TimeUnit.SECONDS);
// 嘗試加鎖,最多等待100秒,上鎖以後10秒自動解鎖
boolean res = rwlock.readLock().tryLock(100, 10, TimeUnit.SECONDS);
// 或
boolean res = rwlock.writeLock().tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();

6.訊號量(Semaphore)

Redisson的分散式訊號量(Semaphore)Java物件RSemaphore採用了與java.util.concurrent.Semaphore相似的介面和用法。

RSemaphore semaphore = redisson.getSemaphore("semaphore");
semaphore.acquire();
//或
semaphore.acquireAsync();
semaphore.acquire(23);
semaphore.tryAcquire();
//或
semaphore.tryAcquireAsync();
semaphore.tryAcquire(23, TimeUnit.SECONDS);
//或
semaphore.tryAcquireAsync(23, TimeUnit.SECONDS);
semaphore.release(10);
semaphore.release();
//或
semaphore.releaseAsync();

7.可過期性訊號量(PermitExpirableSemaphore)

Redisson的可過期性訊號量(PermitExpirableSemaphore)實在RSemaphore物件的基礎上,為每個訊號增加了一個過期時間。每個訊號可以通過獨立的ID來辨識,釋放時只能通過提交這個ID才能釋放。

RPermitExpirableSemaphore semaphore = redisson.getPermitExpirableSemaphore("mySemaphore");
String permitId = semaphore.acquire();
// 獲取一個訊號,有效期只有2秒鐘。
String permitId = semaphore.acquire(2, TimeUnit.SECONDS);
// ...
semaphore.release(permitId);

8.閉鎖(CountDownLatch)

Redisson的分散式閉鎖(CountDownLatch)Java物件RCountDownLatch採用了與java.util.concurrent.CountDownLatch相似的介面和用法。

RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch");
latch.trySetCount(1);
latch.await();
// 在其他執行緒或其他JVM裡
RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch");
latch.countDown();

寫在最後

如果覺得文章對你有點幫助,請微信搜尋並關注「 冰河技術 」微信公眾號,跟冰河學習高併發程式設計技術。

最後,附上併發程式設計需要掌握的核心技能知識圖,祝大家在學習併發程式設計時,少走彎路。

相關推薦

併發知道大家在使用Redisson實現分散式

寫在前面 忘記之前在哪個群裡有朋友在問:有出分散式鎖的文章嗎~@冰河?我的回答是:這週會有,也是【高併發】專題的。想了想,還是先發一個如何使用Redisson實現分散式鎖的文章吧?為啥?因為使用Redisson實現分散式鎖簡單啊!Redisson框架是基於Redis實現的分散式鎖,非常強大,只需要拿來使用就

併發億級流量場景下如何實現分散式限流?看完我徹底懂(文末有福利)

## 寫在前面 > 在網際網路應用中,高併發系統會面臨一個重大的挑戰,那就是大量流高併發訪問,比如:天貓的雙十一、京東618、秒殺、搶購促銷等,這些都是典型的大流量高併發場景。關於秒殺,小夥伴們可以參見我的另一篇文章《[【高併發】高併發秒殺系統架構解密,不是所有的秒殺都是秒殺!](https://mp

併發併發環境下詭異的加問題(加的未必安全)

宣告 特此宣告:文中有關支付寶賬戶的說明,只是用來舉例,實際支付寶賬戶要比文中描述的複雜的多。也與文中描述的完全不同。 前言 很多網友留言說:在編寫多執行緒併發程式時,我明明對共享資源加鎖了啊?為什麼還是出問題呢?問題到底出在哪裡呢?其實,我想說的是:你的加鎖姿勢正確嗎?你真的會使用鎖嗎?錯誤的加鎖方式不但

併發如何設計一個支撐併發大流量的系統?這次我將設計思路分享給大家

## 寫在前面 > 最近不少小夥伴們都在問我:高併發專題我學了不少文章了,但是如何設計一個高併發的系統我還是一臉懵逼!這個問題怎麼解決呢?其實,相信不只是問我的這些小夥伴有這個困惑,就連工作(入坑)了好幾年的開發人員也都有這樣的困惑:我學習了很多的高併發課程,也看了不少的高大上的文章,可就是不知道怎麼

併發壓力測試 java.io.IOException: Too many open files解決方案

 對作業系統做相關的設定,增加最大檔案控制代碼數量。Linux在Linux核心2.4.x中需要修改原始碼,然後重新編譯核心才生效。編輯Linux核心原始碼中的 include/linux/fs.h檔案,將 NR_FILE 由8192改為65536,將NR_RESERVED_FILES 由10 改為 128。編

併發併發秒殺系統架構解密,不是所有的秒殺是秒殺

前言 很多小夥伴反饋說,高併發專題學了那麼久,但是,在真正做專案時,仍然不知道如何下手處理高併發業務場景!甚至很多小夥伴仍然停留在只是簡單的提供介面(CRUD)階段,不知道學習的併發知識如何運用到實際專案中,就更別提如何構建高併發系統了! 究竟什麼樣的系統算是高併發系統?今天,我們就一起解密高併發業務場景

併發學好併發程式設計,關鍵是要理解這三個核心問題

寫在前面 寫【高併發專題】有一段時間了,一些讀者朋友留言說,併發程式設計很難,學習了很多的知識,但是在實際工作中卻無從下手。對於一個線上產生的併發問題,又不知產生這個問題的原因究竟是什麼。對於併發程式設計,感覺上似乎是掌握了,但是真正用起來卻不是那麼回事! 其實,造成這種現象的本質原因就是沒有透徹的理解併發程

併發什麼是ForkJoin?看這一篇就夠

寫在前面 在JDK中,提供了這樣一種功能:它能夠將複雜的邏輯拆分成一個個簡單的邏輯來並行執行,待每個並行執行的邏輯執行完成後,再將各個結果進行彙總,得出最終的結果資料。有點像Hadoop中的MapReduce。 ForkJoin是由JDK1.7之後提供的多執行緒併發處理框架。ForkJoin框架的基本思想是

併發優化加方式時竟然死

寫在前面 今天,在優化程式的加鎖方式時,竟然出現了死鎖!!到底是為什麼呢?!經過仔細的分析之後,終於找到了原因。 為何需要優化加鎖方式? 在《【高併發】高併發環境下詭異的加鎖問題(你加的鎖未必安全)》一文中,我們在轉賬類TansferAccount中使用TansferAccount.class物件對程式加

併發為何併發系統中要使用訊息佇列?這次徹底懂

寫在前面 很多高併發系統中都會使用到訊息佇列中介軟體,那麼,問題來了,為什麼在高併發系統中都會使用到訊息佇列中介軟體呢?立志成為資深架構師的你思考過這個問題嗎? 本文集結了眾多技術大牛的程式設計思想,由冰河匯聚並整理而成,在此,感謝那些在技術發展道理上默默付出的前輩們! 場景分析 現在假設這樣一個場景,使

併發併發環境下該如何構建應用級快取?

寫在前面 隨著我們的系統負載越來越高,系統的效能就會有所下降,此時,我們可以很自然地想到使用快取來解決資料讀寫效能低下的問題。但是,立志成為資深架構師的你,是否能夠在高併發環境下合理並且高效的構建應用級快取呢? 快取命中率 快取命中率是從快取中讀取資料的次數與總讀取次數的比率,命中率越高越好。快取命中率=

併發不廢話,言簡意賅介紹BlockingQueue

寫在前面 最近,有不少網友留言提問:在Java的併發程式設計中,有個BlockingQueue,它是個阻塞佇列,為何要在併發程式設計裡使用BlockingQueue呢?好吧,今天,就臨時說一下BlockingQueue吧,不過今天說的不是很深入,後面咱們一起從源頭上深入剖析這個類。 BlockingQue

併發併發環境下如何防止Tomcat記憶體溢位?看完我懂

寫在前面 隨著系統併發量越來越高,Tomcat所佔用的記憶體就會越來越大,如果對Tomcat的記憶體管理不當,則可能會引發Tomcat記憶體溢位的問題,那麼,如何防止Tomcat記憶體溢位呢?我們今天就來一起探討下這個問題。 防止Tomcat記憶體溢位可以總結為兩個方案:一個是設定Tomcat啟動的初始記

併發併發分散式架構解密,不是所有的分散式

## 寫在前面 > 最近,很多小夥伴留言說,在學習高併發程式設計時,不太明白分散式鎖是用來解決什麼問題的,還有不少小夥伴甚至連分散式鎖是什麼都不太明白。明明在生產環境上使用了自己開發的分散式鎖,為什麼還會出現問題呢?同樣的程式,加上分散式鎖後,效能差了幾個數量級!這又是為什麼呢?今天,我們就來說說如何

併發面試官問我如何使用Nginx實現限流,我如此回答輕鬆拿到Offer

## 寫在前面 > 最近,有不少讀者說看了我的文章後,學到了很多知識,其實我本人聽到後是非常開心的,自己寫的東西能夠為大家帶來幫助,確實是一件值得高興的事情。最近,也有不少小夥伴,看了我的文章後,順利拿到了大廠Offer,也有不少小夥伴一直在刷我的文章,提升自己的內功,最終成為自己公司的核心業務開發人

併發併發環境下構建快取服務需要注意哪些問題?我和阿里P9聊很久

## 寫在前面 > 週末,跟阿里的一個朋友(去年晉升為P9了)聊了很久,聊的內容幾乎全是技術,當然了,兩個技術男聊得最多的話題當然就是技術了。從基礎到架構,從演算法到AI,無所不談。中間又穿插著不少天馬行空的想象,雖然現在看起來不太實際,但是隨著技術的進步,相信五年、十年之後都會實現的。 > &

併發億級流量場景下如何為HTTP介面限流?看完我懂

## 寫在前面 > 在網際網路應用中,高併發系統會面臨一個重大的挑戰,那就是大量流高併發訪問,比如:天貓的雙十一、京東618、秒殺、搶購促銷等,這些都是典型的大流量高併發場景。關於秒殺,小夥伴們可以參見我的另一篇文章《[【高併發】高併發秒殺系統架構解密,不是所有的秒殺都是秒殺!](https://mp

併發Redis如何助力併發秒殺系統,看完這篇我徹底懂

## 寫在前面 > 之前,我們在《[【高併發】高併發秒殺系統架構解密,不是所有的秒殺都是秒殺!](https://mp.weixin.qq.com/s?__biz=Mzg3MzE1NTIzNA==&mid=2247484357&idx=1&sn=23e6e38143704db0

併發面試官:講講什麼是快取穿透?擊穿?雪崩?如何解決?

## 寫在前面 > 在前面的《[【高併發】Redis如何助力高併發秒殺系統?看完這篇我徹底懂了!!](https://mp.weixin.qq.com/s?__biz=Mzg3MzE1NTIzNA==&mid=2247487271&idx=1&sn=6bd9f4627357b1

併發面試官:Java中提供synchronized,為什麼還要提供Lock呢?

## 寫在前面 > 在Java中提供了synchronized關鍵字來保證只有一個執行緒能夠訪問同步程式碼塊。既然已經提供了synchronized關鍵字,那為何在Java的SDK包中,還會提供Lock介面呢?這是不是重複造輪子,多此一舉呢?今天,我們就一起來探討下這個問題。 ## 再造輪子? 既