中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Redisson中怎么實現Redis分布式鎖

發布時間:2021-08-05 14:06:19 來源:億速云 閱讀:166 作者:Leah 欄目:開發技術

Redisson中怎么實現Redis分布式鎖,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

Redis幾種架構

Redis發展到現在,幾種常見的部署架構有:

  • 單機模式;

  • 主從模式;

  • 哨兵模式;

  • 集群模式;

我們首先基于這些架構講解Redisson普通分布式鎖實現,需要注意的是,只有充分了解普通分布式鎖是如何實現的,才能更好的了解Redlock分布式鎖的實現,因為Redlock分布式鎖的實現完全基于普通分布式鎖。

普通分布式鎖

Redis普通分布式鎖這個大家基本上只了解,本文不打算過多的介紹,上一篇文章《Redlock:Redis分布式鎖最牛逼的實現》也講的很細,并且也說到了幾個重要的注意點。

所以直接show you the code,畢竟talk is cheap。

redisson版本

本次測試選擇redisson 2.14.1版本。

單機模式

源碼如下:

// 構造redisson實現分布式鎖必要的Config
Config config = new Config();
config.useSingleServer().setAddress("redis://172.29.1.180:5379").setPassword("a123456").setDatabase(0);
// 構造RedissonClient
RedissonClient redissonClient = Redisson.create(config);
// 設置鎖定資源名稱
RLock disLock = redissonClient.getLock("DISLOCK");
boolean isLock;
try {
    //嘗試獲取分布式鎖
    isLock = disLock.tryLock(500, 15000, TimeUnit.MILLISECONDS);
    if (isLock) {
        //TODO if get lock success, do something;
        Thread.sleep(15000);
    }
} catch (Exception e) {
} finally {
    // 無論如何, 最后都要解鎖
    disLock.unlock();
}

通過代碼可知,經過Redisson的封裝,實現Redis分布式鎖非常方便,我們再看一下Redis中的value是啥,和前文分析一樣,hash結構,key就是資源名稱,field就是UUID+threadId,value就是重入值,在分布式鎖時,這個值為1(Redisson還可以實現重入鎖,那么這個值就取決于重入次數了):

172.29.1.180:5379> hgetall DISLOCK
1) "01a6d806-d282-4715-9bec-f51b9aa98110:1"
2) "1"

哨兵模式

即sentinel模式,實現代碼和單機模式幾乎一樣,唯一的不同就是Config的構造:

Config config = new Config();
config.useSentinelServers().addSentinelAddress(
        "redis://172.29.3.245:26378","redis://172.29.3.245:26379", "redis://172.29.3.245:26380")
        .setMasterName("mymaster")
        .setPassword("a123456").setDatabase(0);

集群模式

集群模式構造Config如下:

Config config = new Config();
config.useClusterServers().addNodeAddress(
        "redis://172.29.3.245:6375","redis://172.29.3.245:6376", "redis://172.29.3.245:6377",
        "redis://172.29.3.245:6378","redis://172.29.3.245:6379", "redis://172.29.3.245:6380")
        .setPassword("a123456").setScanInterval(5000);

總結

普通分布式實現非常簡單,無論是那種架構,向Redis通過EVAL命令執行LUA腳本即可。

Redlock分布式鎖

那么Redlock分布式鎖如何實現呢?以單機模式Redis架構為例,直接看實現代碼:

Config config1 = new Config();
config1.useSingleServer().setAddress("redis://172.29.1.180:5378")
        .setPassword("a123456").setDatabase(0);
RedissonClient redissonClient1 = Redisson.create(config1);

Config config2 = new Config();
config2.useSingleServer().setAddress("redis://172.29.1.180:5379")
        .setPassword("a123456").setDatabase(0);
RedissonClient redissonClient2 = Redisson.create(config2);

Config config3 = new Config();
config3.useSingleServer().setAddress("redis://172.29.1.180:5380")
        .setPassword("a123456").setDatabase(0);
RedissonClient redissonClient3 = Redisson.create(config3);

String resourceName = "REDLOCK";
RLock lock1 = redissonClient1.getLock(resourceName);
RLock lock2 = redissonClient2.getLock(resourceName);
RLock lock3 = redissonClient3.getLock(resourceName);

RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);
boolean isLock;
try {
    isLock = redLock.tryLock(500, 30000, TimeUnit.MILLISECONDS);
    System.out.println("isLock = "+isLock);
    if (isLock) {
        //TODO if get lock success, do something;
        Thread.sleep(30000);
    }
} catch (Exception e) {
} finally {
    // 無論如何, 最后都要解鎖
    System.out.println("");
    redLock.unlock();
}

最核心的變化就是RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);,因為我這里是以三個節點為例。

那么如果是哨兵模式呢?需要搭建3個,或者5個sentinel模式集群(具體多少個,取決于你)。
那么如果是集群模式呢?需要搭建3個,或者5個cluster模式集群(具體多少個,取決于你)。

實現原理

既然核心變化是使用了RedissonRedLock,那么我們看一下它的源碼有什么不同。這個類是RedissonMultiLock的子類,所以調用tryLock方法時,事實上調用了RedissonMultiLock的tryLock方法,精簡源碼如下:

public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
    // 實現要點之允許加鎖失敗節點限制
    int failedLocksLimit = failedLocksLimit();
    List<RLock> acquiredLocks = new ArrayList<RLock>(locks.size());
    // 實現要點之遍歷所有節點通過EVAL命令執行lua加鎖
    for (ListIterator<RLock> iterator = locks.listIterator(); iterator.hasNext();) {
        RLock lock = iterator.next();
        boolean lockAcquired;
        try {
            // 對節點嘗試加鎖
            lockAcquired = lock.tryLock(awaitTime, newLeaseTime, TimeUnit.MILLISECONDS);
        } catch (RedisConnectionClosedException|RedisResponseTimeoutException e) {
            // 如果拋出這類異常,為了防止加鎖成功,但是響應失敗,需要解鎖
            unlockInner(Arrays.asList(lock));
            lockAcquired = false;
        } catch (Exception e) {
            // 拋出異常表示獲取鎖失敗
            lockAcquired = false;
        }
        
        if (lockAcquired) {
            // 成功獲取鎖集合
            acquiredLocks.add(lock);
        } else {
            // 如果達到了允許加鎖失敗節點限制,那么break,即此次Redlock加鎖失敗
            if (locks.size() - acquiredLocks.size() == failedLocksLimit()) {
                break;
            }               
        }
    }
    return true;
}

很明顯,這段源碼就是上一篇文章《Redlock:Redis分布式鎖最牛逼的實現》提到的Redlock算法的完全實現。

以sentinel模式架構為例,如下圖所示,有sentinel-1,sentinel-2,sentinel-3總計3個sentinel模式集群,如果要獲取分布式鎖,那么需要向這3個sentinel集群通過EVAL命令執行LUA腳本,需要3/2+1=2,即至少2個sentinel集群響應成功,才算成功的以Redlock算法獲取到分布式鎖:

Redisson中怎么實現Redis分布式鎖

問題合集

Redisson中怎么實現Redis分布式鎖

根據上面實現原理的分析,這位同學應該是對Redlock算法實現有一點點誤解,假設我們用5個節點實現Redlock算法的分布式鎖。那么要么是5個redis單實例,要么是5個sentinel集群,要么是5個cluster集群。而不是一個有5個主節點的cluster集群,然后向每個節點通過EVAL命令執行LUA腳本嘗試獲取分布式鎖,如上圖所示。

失效時間如何設置
這個問題的場景是,假設設置失效時間10秒,如果由于某些原因導致10秒還沒執行完任務,這時候鎖自動失效,導致其他線程也會拿到分布式鎖。

這確實是Redis分布式最大的問題,不管是普通分布式鎖,還是Redlock算法分布式鎖,都沒有解決這個問題。也有一些文章提出了對失效時間續租,即延長失效時間,很明顯這又提升了分布式鎖的復雜度。另外就筆者了解,沒有現成的框架有實現,如果有哪位知道,可以告訴我,萬分感謝。

redis分布式鎖的高可用
關于Redis分布式鎖的安全性問題,在分布式系統專家Martin Kleppmann和Redis的作者antirez之間已經發生過一場爭論。有興趣的同學,搜索"基于Redis的分布式鎖到底安全嗎"就能得到你想要的答案,需要注意的是,有上下兩篇(這應該就是傳說中的神仙打架吧,哈)。

zookeeper or redis
沒有絕對的好壞,只有更適合自己的業務。就性能而言,redis很明顯優于zookeeper;就分布式鎖實現的健壯性而言,zookeeper很明顯優于redis。如何選擇,取決于你的業務!

關于Redisson中怎么實現Redis分布式鎖問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

治县。| 西宁市| 兴国县| 淳安县| 公安县| 昌乐县| 古丈县| 绥芬河市| 土默特左旗| 武功县| 华宁县| 淮滨县| 奇台县| 洞头县| 安岳县| 乌兰察布市| 江安县| 育儿| 泰顺县| 临澧县| 色达县| 栾城县| 涞源县| 穆棱市| 乐安县| 洪雅县| 饶平县| 砚山县| 韩城市| 井研县| 永安市| 满城县| 黔西| 册亨县| 钦州市| 舟山市| 兰州市| 永福县| 永康市| 广河县| 宁阳县|