redis的分布式鎖框架redisson之體驗分布式鎖


使用

1、引入依賴:

<!--以后使用redis作為所有分布式鎖,分布式對象等功能框架-->
<!-- https://mvnrepository.com/artifact/org.redisson/redisson -->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.12.0</version>
</dependency>

2、程序化配置方法

@Configuration
public class MyRedisConfig {

    @Bean(destroyMethod="shutdown")
    public RedissonClient redisson() throws IOException {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("li199852");
        RedissonClient redisson = Redisson.create(config);
        return redisson;
    }
}

以后操作都是使用redissonClient操作:

@Autowired
RedissonClient redissonClient;

4、可重入鎖(Reentrant Lock)

他的使用和java的Lack鎖差不多:

@GetMapping("/hello")
@ResponseBody
public String hello(){
    //1.獲取一把鎖,只要鎖的名字一樣,就是同一把鎖
    RLock lock = redisson.getLock("my-lock");
    //2.加鎖
    lock.lock();//原理是阻塞式等待,默認加的鎖都是30s的時間
    /*
    問題:lock.lock(10, TimeUnit.SECONDS)鎖到期之后,不會自動續期。
        1、如果我們傳遞了鎖的超時時間,就發送給redis執行腳本,進行占鎖,默認超時就是我們指定的時間
        2、如果我們未指定鎖的超時時間,就使用30*1000【lockWatchdogTimeout看門狗的默認時間】;
            只要占鎖成功,就會啟動一個定時任務【重新給鎖設置過期時間,新的過期時間就是看門狗的默認時間】
            initernallockLeaseTime【看門狗時間】 / 3 ,也就是10秒調用一次重置時間方法

    */
    /*
    優點:
        1)、鎖的自動續期,如果業務超長,運行期間自動給鎖鎖上新的30s。不用擔心業務時間長,鎖自動被刪掉
        2)、加鎖的業務自動運行完成,就不會給當前鎖續期,即使不手動解鎖,鎖默認會在30s以后自動刪除
    */
    try {
        System.out.println("我拿到了鎖"+Thread.currentThread().getId());
            Thread.sleep(20000);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        //3.解鎖,假設解鎖代碼沒有運行,redisson會不會出現死鎖:不會,鎖默認會在30s以后自動刪除
        System.out.println("我釋放了鎖"+Thread.currentThread().getId());
        lock.unlock();
    }
    return "hello";
}

 推薦使用:

  可以省掉續期的操作,如果業務30秒還執行不完,就要改造業務了;

lock.lock(30, TimeUnit.SECONDS);//鎖到期之后,不會自動續期,需要手動解鎖。

 

5、讀寫鎖(ReadWriteLock)

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

    @RequestMapping("/read")
    @ResponseBody
    public String readString() {
        RReadWriteLock readWriteLock = redisson.getReadWriteLock("readWriteLock");
        RLock rLock = readWriteLock.readLock();
        String s = "";
        try {
            rLock.lock(20,TimeUnit.SECONDS);
            s =  redisTemplate.opsForValue().get("s");
        }finally {
            rLock.unlock();
        }

        return s;
    }

 

6、信號量(Semaphore)(還有一個可過期性信號量(PermitExpirableSemaphore))

    /**
* 信號量(Semaphore)
* 默認是獲取的
* @return
*/
@RequestMapping("/goOneCar")
@ResponseBody
public String goOneCar(){
RSemaphore semaphore = redisson.getSemaphore("semaphore-Lock");
semaphore.release();//釋放當前一個車位
return "出去一輛車";
}

@RequestMapping("/comeOneCar")
@ResponseBody
public String comeOneCar() throws InterruptedException {
RSemaphore semaphore = redisson.getSemaphore("semaphore-Lock");
// semaphore.acquire();//獲取當前一個車位
semaphore.tryAcquire(10);//嘗試獲取當前十個車位,沒有或不夠就算了
return "進來一輛車";
}

 

7、閉鎖(CountDownLatch)

    /**
     * 閉鎖:CountDownLatch
     * 五個人都走出教室了在鎖門,
     */
    //鎖門
    @RequestMapping("/closeDoor")
    @ResponseBody
    public String closeDoor() throws InterruptedException {
        RCountDownLatch countDownLatch = redisson.getCountDownLatch("countDownLatch-Lack");
        countDownLatch.trySetCount(5);
        countDownLatch.await();
        return "門鎖了";
    }

    //出去
    @RequestMapping("/goOut")
    @ResponseBody
    public String goOut(Long id){
        RCountDownLatch countDownLatch = redisson.getCountDownLatch("countDownLatch-Lack");
        countDownLatch.countDown();
        return id+"出去了";
    }

 

其他可以參考redis官網,鏈接:https://github.com/redisson/redisson/wiki/8.-%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E5%92%8C%E5%90%8C%E6%AD%A5%E5%99%A8


免責聲明!

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



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