https://github.com/redisson/redisson/wiki/2.-%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95#26-%E5%8D%95redis%E8%8A%82%E7%82%B9%E6%A8%A1%E5%BC%8F
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.14.1</version> </dependency>
以配置類的形式設(shè)置
?
?
@Configuration public class MyRedisConfig { @Bean public RedissonClient redissonClient(){ Config config = new Config(); //配置鏈接的信息 config.useSingleServer().setAddress("redis://192.168.1.137:6379"); RedissonClient redissonClient = Redisson.create(); return redissonClient; } }
ls -l /proc/7579/cwd
接下來我們看 分布式鎖 的可重入鎖(Reentrant Lock) 同一個(gè)對(duì)象的同一把鎖 是可以進(jìn)入
?
@ResponseBody @GetMapping("/hello") public String hello(){ RLock myLock = redissonClient.getLock("myLock"); // 加鎖 // myLock.lock(); //通過效果演示我們可以發(fā)現(xiàn) 指定了過期時(shí)間后 自動(dòng)續(xù)期就不會(huì)生效了 這時(shí)我們就需要注意設(shè)置過期時(shí)間一定要滿足我們得業(yè)務(wù)場(chǎng)景 默認(rèn)情況下,看門狗的檢查鎖的超時(shí)時(shí)間是30秒鐘,也可以通過yml修改Config.lockWatchdogTimeout來另行指定
另外Redisson還通過加鎖的方法提供了leaseTime
的參數(shù)來指定加鎖的時(shí)間。超過這個(gè)時(shí)間后鎖便自動(dòng)解開了。
// 加鎖以后10秒鐘自動(dòng)解鎖 // 無需調(diào)用unlock方法手動(dòng)解鎖 lock.lock(10, TimeUnit.SECONDS); // 嘗試加鎖,最多等待100秒,上鎖以后10秒自動(dòng)解鎖 boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS); if (res) { try { ... } finally { lock.unlock(); } }
//如果我們指定了鎖的過期時(shí)間 那么在源碼中會(huì)直接幫我們創(chuàng)建一個(gè)過期時(shí)間是指定的鎖 時(shí)間到期后就會(huì)把該鎖刪除 //如果我們沒有指定過期時(shí)間 那么在執(zhí)行的時(shí)候 首先會(huì)創(chuàng)建一把鎖且過期時(shí)間是30秒 然后會(huì)創(chuàng)建異步任務(wù) 每隔10秒 去執(zhí)行任務(wù)來續(xù)期 //實(shí)際開發(fā)中 我們最好指定過期時(shí)間---》性能考慮--》計(jì)算代碼的執(zhí)行時(shí)間 myLock.lock(10, TimeUnit.SECONDS);//過期時(shí)間是10s 業(yè)務(wù)時(shí)間超過10s 會(huì)不會(huì)自動(dòng)續(xù)期 try { System.out.println("加鎖成功...業(yè)務(wù)處理....." + Thread.currentThread().getName()); Thread.sleep(30000); }catch (Exception e){ }finally { System.out.println("釋放鎖成功..." + Thread.currentThread().getName()); // 釋放鎖 myLock.unlock(); } return "hello"; }
公平鎖(Fair Lock)保證了當(dāng)多個(gè)Redisson客戶端線程同時(shí)請(qǐng)求加鎖時(shí),優(yōu)先分配給先發(fā)出請(qǐng)求的線程。所有請(qǐng)求線程會(huì)在一個(gè)隊(duì)列中排隊(duì),當(dāng)某個(gè)線程出現(xiàn)宕機(jī)時(shí),
Redisson會(huì)等待5秒后繼續(xù)下一個(gè)線程,也就是說如果前面有5個(gè)線程都處于等待狀態(tài),那么后面的線程會(huì)等待至少25秒。
RLock fairLock = redisson.getFairLock("anyLock");
// 最常見的使用方法
fairLock.lock();
大家都知道,如果負(fù)責(zé)儲(chǔ)存這個(gè)分布式鎖的Redis節(jié)點(diǎn)宕機(jī)以后,而且這個(gè)鎖正好處于鎖住的狀態(tài)時(shí),這個(gè)鎖會(huì)出現(xiàn)鎖死的狀態(tài)。為了避免這種情況的發(fā)生,Redisson內(nèi)部提供了一個(gè)監(jiān)控鎖的看門狗,它的作用是在Redisson實(shí)例被關(guān)閉前,不斷的延長鎖的有效期。默認(rèn)情況下,看門狗的檢查鎖的超時(shí)時(shí)間是30秒鐘,也可以通過修改Config.lockWatchdogTimeout來另行指定。
另外Redisson還通過加鎖的方法提供了leaseTime
的參數(shù)來指定加鎖的時(shí)間。超過這個(gè)時(shí)間后鎖便自動(dòng)解開了。
// 10秒鐘以后自動(dòng)解鎖
// 無需調(diào)用unlock方法手動(dòng)解鎖
fairLock.lock(10, TimeUnit.SECONDS);
// 嘗試加鎖,最多等待100秒,上鎖以后10秒自動(dòng)解鎖
boolean res = fairLock.tryLock(100, 10, TimeUnit.SECONDS);
...
fairLock.unlock();
讀寫鎖(ReadWriteLock)分布式可重入讀寫鎖允許同時(shí)有多個(gè)讀鎖和一個(gè)寫鎖處于加鎖狀態(tài)。
RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock");
// 最常見的使用方法
rwlock.readLock().lock();
// 或
rwlock.writeLock().lock();
大家都知道,如果負(fù)責(zé)儲(chǔ)存這個(gè)分布式鎖的Redis節(jié)點(diǎn)宕機(jī)以后,而且這個(gè)鎖正好處于鎖住的狀態(tài)時(shí),這個(gè)鎖會(huì)出現(xiàn)鎖死的狀態(tài)。為了避免這種情況的發(fā)生,Redisson內(nèi)部提供了一個(gè)監(jiān)控鎖的看門狗,它的作用是在Redisson實(shí)例被關(guān)閉前,不斷的延長鎖的有效期。默認(rèn)情況下,看門狗的檢查鎖的超時(shí)時(shí)間是30秒鐘,也可以通過修改Config.lockWatchdogTimeout來另行指定。
另外Redisson還通過加鎖的方法提供了leaseTime
的參數(shù)來指定加鎖的時(shí)間。超過這個(gè)時(shí)間后鎖便自動(dòng)解開了。
// 10秒鐘以后自動(dòng)解鎖
// 無需調(diào)用unlock方法手動(dòng)解鎖
rwlock.readLock().lock(10, TimeUnit.SECONDS);
// 或
rwlock.writeLock().lock(10, TimeUnit.SECONDS);
// 嘗試加鎖,最多等待100秒,上鎖以后10秒自動(dòng)解鎖
boolean res = rwlock.readLock().tryLock(100, 10, TimeUnit.SECONDS);
// 或
boolean res = rwlock.writeLock().tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();
-------------------------------------------------------------
根據(jù)業(yè)務(wù)操作我們可以分為讀寫操作,讀操作其實(shí)不會(huì)影響數(shù)據(jù),那么如果還對(duì)讀操作做串行處理,效率會(huì)很低,這時(shí)我們可以通過讀寫鎖來解決這個(gè)問題
在讀寫鎖中,只有讀讀的行為是共享鎖,相互之間不影響,只要有寫的行為存在,那么就是一個(gè)互斥鎖(排他鎖)
---------------------------------------------------------------------------------------------
@GetMapping("/write") @ResponseBody public String writeValue(){ RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("rw-lock"); //加寫鎖 RLock rLock = readWriteLock.writeLock(); String s=null; rLock.lock(); try { System.out.println("寫鎖成功"); s = UUID.randomUUID().toString(); stringRedisTemplate.opsForValue().set("msg", s); Thread.sleep(30000); } catch (InterruptedException e) { e.printStackTrace(); }finally { rLock.unlock(); } return s; } /** * 讀讀操作 相當(dāng)于沒有加鎖 * 寫 讀操作 需要等待寫鎖釋放 讀鎖才能讀取 阻塞 * 寫 寫 阻塞方式 * 讀寫 讀數(shù)據(jù)的時(shí)候也會(huì)添加鎖 那么寫的行為也會(huì)阻塞 * @return */ @GetMapping("/read") @ResponseBody public String readValue(){ RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("rw-lock"); //加讀鎖 RLock rLock = readWriteLock.readLock(); rLock.lock(); String s = null; try { System.out.println("讀鎖成功"); s = stringRedisTemplate.opsForValue().get("msg"); Thread.sleep(30000); } catch (Exception e) { e.printStackTrace(); } finally { // rLock.unlock(); } return s; }
?
閉鎖 基于Redisson的Redisson分布式閉鎖 @ResponseBody @GetMapping("/lockDoor") public String lockDoor() { RCountDownLatch door = redissonClient.getCountDownLatch("door");//阻塞 等待count 等于0 時(shí)才能繼續(xù)執(zhí)行 door.trySetCount(5); try { door.await();//阻塞等待5個(gè)執(zhí)行完 } catch (InterruptedException e) { e.printStackTrace(); } return "關(guān)門熄燈"; } @GetMapping("/goHome/{id}") @ResponseBody public String goHome(@PathVariable Long id){ RCountDownLatch door = redissonClient.getCountDownLatch("door"); door.countDown(); return id+"下班走人"; }
信號(hào)量(Semaphore) 基于Redis的Redisson的分布式信號(hào)量 限流 @GetMapping("/park") @ResponseBody public String park(){ RSemaphore park = redissonClient.getSemaphore("park"); boolean b = true; try { // park.acquire(); // 獲取信號(hào) 阻塞到獲取成功 b = park.tryAcquire();// 返回獲取成功還是失敗 } catch (Exception e) { e.printStackTrace(); } return "停車是否成功:" + b; } @GetMapping("/release") @ResponseBody public String release(){ RSemaphore park = redissonClient.getSemaphore("park"); park.release(); return "釋放了一個(gè)車位"; }
?
本文摘自 :https://www.cnblogs.com/