谷粒商城Redisson分布式鎖(二十四)


 159、緩存-分布式鎖-Redisson簡介&整合 - 166、緩存-分布式鎖-緩存一致性解決

 官網說明:https://github.com/redisson/redisson

 反正也很詳細,有說明,也有配置的用法,感興趣的可以具體看一下。底層也是用到lua腳本

    /**
     * 簡單請求
     * @return
     */
    @ResponseBody
    @GetMapping("/hello")
    public String hello() {
        RLock rLock = redisson.getLock("my-lock");
        //1.鎖的自動續期,如果業務超長,運行期間會自動給鎖續上新的30s。不用擔心業務時間長,鎖自動被刪掉
        //2.加鎖的業務只要運行完成,就不會給當前鎖續期,即使不手動解鎖,鎖默認在30s以后自動刪除。
        //rLock.lock();
        rLock.lock(30, TimeUnit.SECONDS);  //10秒自動解鎖,自動解鎖時間一定要大於業務的執行時間
        //問題:rLock.lock(10, TimeUnit.SECONDS);  在鎖時間到了以后,不會自動續期
        //1.如果我們傳遞了鎖的超時時間,就發送給redis執行腳本,進行占鎖,默認超時就是我們指定的時間。
        //2.如果我們未指定鎖的超時時間,就使用30*1000的LockWatchTimeout看門狗的默認時間;
        // 只要占鎖成功,就會啟動一個定時任務,每隔10s都會自動續期
        //建議; rLock.lock(30, TimeUnit.SECONDS); 省掉了續期的時間
        try {
            System.out.println("加鎖成功,執行業務"+Thread.currentThread().getId());
            Thread.sleep(30000);
        }catch(Exception e){

        }finally {
            System.out.println("釋放鎖"+Thread.currentThread().getId());
            rLock.unlock();
        }

        

 

 

    //保證一定能讀到最新數據,修改期間,寫鎖是一個排他鎖(互斥鎖)。讀鎖是一個共享鎖
    //寫鎖沒釋放讀就必須等待
    //讀 + 讀: 相當於無鎖,並發讀,只會在redis中記錄好,所有當前的讀鎖。他們都會同時加鎖成功
    //寫 + 讀: 等待寫鎖釋放
    //寫 + 寫: 阻塞方式
    //讀 + 寫: 有讀鎖。寫也需要等待
    //只要有寫的存在,都必須等待。
    @GetMapping("/write")
    @ResponseBody
    public String writeValue(){
        RReadWriteLock lock = redisson.getReadWriteLock("rw-lock");
        String s = "";
        RLock rLock = lock.writeLock();
        try {
            rLock.lock();
            s = UUID.randomUUID().toString();
            redisTemplate.opsForValue().set("writeValue",s);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            rLock.unlock();
        }
        return  s;

    }

    @GetMapping("/read")
    @ResponseBody
    public String read(){
        RReadWriteLock lock = redisson.getReadWriteLock("rw-lock");
        String s = "";
        RLock rLock = lock.readLock();
        try {
            rLock.lock();
            Thread.sleep(30000);
            s = redisTemplate.opsForValue().get("writeValue");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            rLock.unlock();
        }
        return  s;

    }

讀寫鎖(ReadWriteLock)

 

基於Redis的Redisson分布式可重入讀寫鎖RReadWriteLock Java對象實現了java.util.concurrent.locks.ReadWriteLock接口。其中讀鎖和寫鎖都繼承了RLock接口。

 

分布式可重入讀寫鎖允許同時有多個讀鎖和一個寫鎖處於加鎖狀態。

 

RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock");
// 最常見的使用方法
rwlock.readLock().lock();
//
rwlock.writeLock().lock();

 

 

大家都知道,如果負責儲存這個分布式鎖的Redis節點宕機以后,而且這個鎖正好處於鎖住的狀態時,這個鎖會出現鎖死的狀態。為了避免這種情況的發生,Redisson內部提供了一個監控鎖的看門狗,它的作用是在Redisson實例被關閉前,不斷的延長鎖的有效期。默認情況下,看門狗的檢查鎖的超時時間是30秒鍾,也可以通過修改Config.lockWatchdogTimeout來另行指定。

 

另外Redisson還通過加鎖的方法提供了leaseTime的參數來指定加鎖的時間。超過這個時間后鎖便自動解開了。

 

// 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();

閉鎖(CountDownLatch)

基於Redisson的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();
    @GetMapping("/lockDoor")
    @ResponseBody
    public  String lockDoor () throws InterruptedException {
        RCountDownLatch door = redisson.getCountDownLatch("door");
        door.trySetCount(5);
        door.await();
        return "放假了。。。";
    }

    @GetMapping("/gogogo/{id}")
    @ResponseBody
    public String gogogo(@PathVariable("id") Long id){
        RCountDownLatch door = redisson.getCountDownLatch("door");
        door.countDown();
        return id+"班的人都走了";
    }

信號量(Semaphore)

基於Redis的Redisson的分布式信號量(Semaphore)Java對象RSemaphore采用了與java.util.concurrent.Semaphore相似的接口和用法。同時還提供了異步(Async)、反射式(Reactive)和RxJava2標准的接口。

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();

 

 加上Redisson鎖

    //Redisson加上分布式鎖
    public Map<String, List<Catalog2Vo>> getCatalogJsonFromDbRedissonLock() {
        RLock lock = redisson.getLock("catalogSon-lock");
        lock.lock();
        log.info("分布式加鎖成功");
        Map<String, List<Catalog2Vo>> dataFromDb;
        try{
            dataFromDb = getDataFromDb();
        }finally{
            lock.unlock();
            log.info("分布式解鎖成功");
        }
        return dataFromDb;
    }

 

 解決方案:

 

 

 canal還是很有用的,等后面擴大了服務器的內存,在加入一下。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM