最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

redis深入淺出分布式鎖實現(xiàn)下篇

 更新時間:2022年08月30日 17:10:40   作者:一個風輕云淡  
在單體應用中,如果我們對共享數(shù)據(jù)不進行加鎖操作,會出現(xiàn)數(shù)據(jù)一致性問題,我們的解決辦法通常是加鎖。下面我們一起聊聊使用redis來實現(xiàn)分布式鎖

優(yōu)化之UUID防誤刪

問題:刪除操作缺乏原子性。

場景:

index1執(zhí)行刪除時,查詢到的lock值確實和uuid相等

uuid=v1

set(lock,uuid);

index1執(zhí)行刪除前,lock剛好過期時間已到,被redis自動釋放,在redis中沒有了lock,沒有了鎖。

index2獲取了lock

index2線程獲取到了cpu的資源,開始執(zhí)行方法

uuid=v2

set(lock,uuid);

index1執(zhí)行刪除,此時會把index2的lock刪除

index1 因為已經(jīng)在方法中了,所以不需要重新上鎖。index1有執(zhí)行的權(quán)限。index1已經(jīng)比較完成了,這個時候,開始執(zhí)行

刪除的index2的鎖!

優(yōu)化之LUA腳本保證刪除的原子性

@GetMapping("testLockLua")
public void testLockLua() {
    //1 聲明一個uuid ,將做為一個value 放入我們的key所對應的值中
    String uuid = UUID.randomUUID().toString();
    //2 定義一個鎖:lua 腳本可以使用同一把鎖,來實現(xiàn)刪除!
    String skuId = "25"; // 訪問skuId 為25號的商品 100008348542
    String locKey = "lock:" + skuId; // 鎖住的是每個商品的數(shù)據(jù)
   // 3 獲取鎖
    Boolean lock = redisTemplate.opsForValue().setIfAbsent(locKey, uuid, 3, TimeUnit.SECONDS);
    // 第一種: lock 與過期時間中間不寫任何的代碼。
    // redisTemplate.expire("lock",10, TimeUnit.SECONDS);//設置過期時間
    // 如果true
    if (lock) {
        // 執(zhí)行的業(yè)務邏輯開始
        // 獲取緩存中的num 數(shù)據(jù)
        Object value = redisTemplate.opsForValue().get("num");
        // 如果是空直接返回
        if (StringUtils.isEmpty(value)) {
            return;
        }
        // 不是空 如果說在這出現(xiàn)了異常! 那么delete 就刪除失敗! 也就是說鎖永遠存在!
        int num = Integer.parseInt(value + "");
        // 使num 每次+1 放入緩存
        redisTemplate.opsForValue().set("num", String.valueOf(++num));
        /*使用lua腳本來鎖*/
        // 定義lua 腳本
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        // 使用redis執(zhí)行l(wèi)ua執(zhí)行
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(script);
        // 設置一下返回值類型 為Long
        // 因為刪除判斷的時候,返回的0,給其封裝為數(shù)據(jù)類型。如果不封裝那么默認返回String 類型,
        // 那么返回字符串與0 會有發(fā)生錯誤。
        redisScript.setResultType(Long.class);
        // 第一個要是script 腳本 ,第二個需要判斷的key,第三個就是key所對應的值。
        redisTemplate.execute(redisScript, Arrays.asList(locKey), uuid);
    } else {
        // 其他線程等待
        try {
            // 睡眠
            Thread.sleep(1000);
            // 睡醒了之后,調(diào)用方法。
            testLockLua();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Lua 腳本詳解:

項目中正確使用

定義key,key應該是為每個sku定義的,也就是每個sku有一把鎖。

String locKey ="lock:"+skuId; // 鎖住的是每個商品的數(shù)據(jù)
Boolean lock = redisTemplate.opsForValue().setIfAbsent(locKey, uuid,3,TimeUnit.SECONDS);

總結(jié)

加鎖

使用lua釋放鎖

重試

為了確保分布式鎖可用,我們至少要確保鎖的實現(xiàn)同時滿足以下四個條件:

- 互斥性。在任意時刻,只有一個客戶端能持有鎖。

- 不會發(fā)生死鎖。即使有一個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保證后續(xù)其他客戶端能加鎖。

- 解鈴還須系鈴人。加鎖和解鎖必須是同一個客戶端,客戶端自己不能把別人加的鎖給解了。

- 加鎖和解鎖必須具有原子性

到此這篇關(guān)于redis深入淺出分布式鎖實現(xiàn)下篇的文章就介紹到這了,更多相關(guān)redis分布式鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot事件機制相關(guān)知識點匯總

    SpringBoot事件機制相關(guān)知識點匯總

    這篇文章主要介紹了SpringBoot事件機制相關(guān)知識點匯總,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • java ThreadPoolExecutor線程池拒絕策略避坑

    java ThreadPoolExecutor線程池拒絕策略避坑

    這篇文章主要為大家介紹了java ThreadPoolExecutor拒絕策略避坑踩坑示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • java數(shù)組及arrays類對數(shù)組的操作實例

    java數(shù)組及arrays類對數(shù)組的操作實例

    下面小編就為大家?guī)硪黄猨ava數(shù)組及arrays類對數(shù)組的操作實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • Java中Getter和Setter方法及主要區(qū)別

    Java中Getter和Setter方法及主要區(qū)別

    這篇文章主要給大家介紹了關(guān)于Java中Getter和Setter方法及主要區(qū)別的相關(guān)資料,getter和setter方法是用于封裝類中的私有屬性的方法,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-04-04
  • Java文件上傳下載、郵件收發(fā)實例代碼

    Java文件上傳下載、郵件收發(fā)實例代碼

    這篇文章主要介紹了Java文件上傳下載、郵件收發(fā)實例代碼的相關(guān)資料,非常不錯具有參考借鑒價值,需要的朋友可以參考下
    2016-06-06
  • Java實現(xiàn)五子棋單機版

    Java實現(xiàn)五子棋單機版

    這篇文章主要為大家詳細介紹了Java實現(xiàn)五子棋單機版,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • SpringBoot中MyBatis使用自定義TypeHandler的實現(xiàn)

    SpringBoot中MyBatis使用自定義TypeHandler的實現(xiàn)

    本文主要介紹了SpringBoot中MyBatis使用自定義TypeHandler,當默認的類型映射不能滿足需求時,自定義?TypeHandler?就非常有用,具有一定的參考價值,感興趣的可以了解一下
    2024-08-08
  • idea?2024使用Maven創(chuàng)建Java?Web項目詳細圖文教程

    idea?2024使用Maven創(chuàng)建Java?Web項目詳細圖文教程

    這篇文章主要給大家介紹了關(guān)于idea?2024使用Maven創(chuàng)建Java?Web項目的相關(guān)資料,介紹了如何使用Maven創(chuàng)建一個Spring?MVC項目,并配置Tomcat服務器以運行一個簡單的Helloworld?JSP頁面,需要的朋友可以參考下
    2024-12-12
  • Java基于接口實現(xiàn)模擬動物聲音代碼實例

    Java基于接口實現(xiàn)模擬動物聲音代碼實例

    這篇文章主要介紹了Java基于接口實現(xiàn)模擬動物聲音代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • 微服務Spring?Boot?整合Redis?阻塞隊列實現(xiàn)異步秒殺下單思路詳解

    微服務Spring?Boot?整合Redis?阻塞隊列實現(xiàn)異步秒殺下單思路詳解

    這篇文章主要介紹了微服務Spring?Boot?整合Redis?阻塞隊列實現(xiàn)異步秒殺下單,使用阻塞隊列實現(xiàn)秒殺的優(yōu)化,采用異步秒殺完成下單的優(yōu)化,本文給大家分享詳細步驟及實現(xiàn)思路,需要的朋友可以參考下
    2022-10-10

最新評論

内黄县| 安溪县| 龙陵县| 东莞市| 娄底市| 莎车县| 遂昌县| 保靖县| 华蓥市| 嵊州市| 揭阳市| 贺州市| 耿马| 木兰县| 屏东市| 穆棱市| 年辖:市辖区| 垣曲县| 明星| 泰安市| 革吉县| 瑞金市| 开阳县| 四川省| 阿荣旗| 曲沃县| 苗栗县| 额尔古纳市| 山阳县| 邛崃市| 延寿县| 沾益县| 竹北市| 云浮市| 瓦房店市| 富宁县| 察隅县| 井陉县| 新河县| 临夏县| 将乐县|