1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Redisson 分布式鎖源碼 01:可重入鎖加鎖

        共 2678字,需瀏覽 6分鐘

         ·

        2021-06-27 00:12

        前言

        相信小伙伴都是使用分布式服務,那一定繞不開分布式服務中數(shù)據(jù)并發(fā)更新問題!

        單系統(tǒng)很容易想到 Java 的各種鎖,像 synchronize、ReentrantLock 等等等,那分布式系統(tǒng)如何處理?

        當然是使用分布式鎖。

        如果小伙伴不知道什么是分布式鎖,那推薦看看石杉老師的突擊課或者在網(wǎng)上搜一搜相關資料。

        當使用 Redis 作為分布式鎖時,當前使用較多的框架就是 Redisson。

        當然 Redisson 也不僅僅只能當做鎖來使用,也有很多其他的功能,小伙伴們可以看一看官方文檔,自己多動手實踐一下。

        下面就開始記錄 Redisson 的相關筆記!錯誤之處,歡迎指正。????

        1

        環(huán)境配置

        • 本地環(huán)境搭建的偽集群:
        • redisson 3.15.6

        不同版本可能會有所不同,但是核心思想不會發(fā)生太大變化,如果變化很大,希望可以留言。

        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.15.6</version>
        </dependency>
        • 項目準備

        一個簡單的 maven 項目,只需要一個 Main 方法即可。

        2

        可重入鎖加鎖

        在 lock.lock() 斷點,作為源碼入口。

        默認加鎖,什么參數(shù)也沒有傳遞。但是這里會設置 leaseTime = -1。這個 leaseTime 的含義是加鎖的時間。

        剩下的一路挺進即可。

        在調用 tryAcquire 方法之前,多了一個參數(shù) threadId,是當前線程的 id,long 型正數(shù)。

        異步加鎖

        直接來到 tryAcquireAsync 異步加鎖方法。

        tryAcquireAsync

        前面已經(jīng)說了 leaseTime 是 -1,所以這里會走到下面的方法中。

        至此幾個參數(shù)已經(jīng)清楚:

        1. waitTime:-1;
        2. internalLockLeaseTime:使用默認時間 30000 毫秒;
        3. TimeUnit.MILLISECONDS:單位毫秒;
        4. threadId:線程 id;
        5. RedisCommands.EVAL_LONG:eval。

        Redis eval 命令的相關文檔可以閱讀:https://redis.io/commands/eval

        加鎖邏輯

        真正的加鎖,其實就是這么一段 lua 腳本。

        先說明一下 lua 腳本的參數(shù)信息:

        1. KEYS[1]:getRawName(),加鎖的 key ,比如 anyLock;
        2. ARGV[1]:unit.toMillis(leaseTime),鎖的毫秒時間,比如 30000;
        3. ARGV[2]:getLockName(threadId),是 UUID 和線程 id 拼接起來的字符串,比如 931573de-903e-42fd-baa7-428ebb7eda80:1。

        因為使用的是 lua 腳本,可以保證這一塊 lua 腳本的原子性。

        首次加鎖分析:

        1. exists 命令判斷 redis anyLock 是否存在;
        2. 不存在,使用 hincrby 命令,創(chuàng)建 anyLock 數(shù)據(jù);
        3. 對 anyLock 設置過期時間。

        加鎖后 Redis 內的數(shù)據(jù)格式是:

        關于 Redis 的 Hash 數(shù)據(jù)結構可以閱讀:https://redis.io/topics/data-types#hashes

        抽象一點可以理解為 anyLock 下面掛著一個 K-V 結構的數(shù)據(jù):

        "anyLock":{
            "f400aad5-4b1f-4246-a81e-80c2717c3afb:1":"1"
        }

        執(zhí)行腳本

        后續(xù)的內容就是進行請求執(zhí)行 lua 腳本,唯一需要注意的地方就是有個哈希槽路由。

        這塊代碼是在 CommandAsyncService#evalWriteAsync 方法處調用的,是為了獲取一個 NodeSource。

        當然這個 NodeSource 里面只存放了一個 slot(哈希槽值)。

        這個 slot 值是對加鎖的 key 使用 CRC16 算法計算出來的。

        // MAX_SLOT 默認 16384
        int result = CRC16.crc16(key.getBytes()) % MAX_SLOT;

        這塊計算一個 slot 到底有什么用呢?

        繼續(xù)追蹤!

        BaseRedisBatchExecutor#addBatchCommandData 在這里會從 source 里面獲取到 solt,然后獲得 MasterSlaveEntry。

        大概可以理解為這里是獲取到這個 Redis key 對應的節(jié)點。

        可重入

        既然是可重入鎖,這塊是支持可重入的,來看下可重入是如何保證的。

        1. exists 命令判斷 redis key field 是否存在;
        2. 存在 則通過 hincrby 命令對 key 的 field 對應 value 自增;
        3. 為當前 redis key 設置過期時間。

        加鎖互斥

        上面已經(jīng)驗證了兩種情況:

        1. redis key 不存在;
        2. redis key 和 key 的 field 存在。

        剩下的情況就是 key 存在的情況下,但是 field 不存在。

        要知道 key 的 field 放的是 UUID:ThreadId,說明加鎖的不是當前線程。這時候直接返回當前鎖的剩余時間。

        3

        總結

        本文主要介紹了 Redisson 可重入鎖的加鎖、鎖重入、鎖互斥邏輯。

        核心重點在 lua 腳本。同時需要理解 Redis 的 Hash 數(shù)據(jù)結構。

        同時需要記住,在未指定加鎖時間時,默認使用的是 30s。

        最后,一張圖介紹本文加鎖邏輯。

        - <End /> -




        歷史文章 | 相關推薦




        瀏覽 35
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            乱人伦 国语对白 | 超逼网| 国内一级视频 | 欧美V亚洲V日韩v | 91麻豆精品国产理伦片在线观看 | 天天曰天天日 | 福利国产在线 | 五月婷香蕉久色在线看 | Avove无套劲爆刺激在线 | 涩色av |