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