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

基于Redis的分布式鎖及原子性問題(短視頻開發(fā))

 更新時間:2025年06月21日 09:00:29   作者:云豹科技-蘇凌霄  
短視頻開發(fā)中,Redis分布式鎖通過SETNX實現(xiàn)加鎖與解鎖,需設置超時時間避免死鎖,為防止誤刪,釋放鎖時需判斷線程身份,并用Lua腳本保證原子性,確保安全操作,本文給大家介紹基于Redis的分布式鎖及原子性問題,感興趣的朋友一起看看吧

短視頻開發(fā),基于Redis的分布式鎖及原子性問題

用 Redis 實現(xiàn)分布式鎖

主要應用到的是 SETNX key value命令(如果不存在,則設置)

主要要實現(xiàn)兩個功能:

1、獲取鎖(設置一個 key)
2、釋放鎖 (刪除 key)
基本思想是執(zhí)行了 SETNX命令的線程獲得鎖,在完成操作后,需要刪除 key,釋放鎖。

加鎖:

@Override
public boolean tryLock(long timeoutSec) {
    // 獲取線程標示
    String threadId = ID_PREFIX + Thread.currentThread().getId();
    // 獲取鎖
    Boolean success = stringRedisTemplate.opsForValue()
            .setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
    return Boolean.TRUE.equals(success);
}

釋放鎖:

@Override
public void unlock() {
    // 獲取線程標示
    String threadId = ID_PREFIX + Thread.currentThread().getId();
    // 獲取鎖中的標示
    String id = stringRedisTemplate.opsForValue().get(KEY_PREFIX + name);
    // 釋放鎖
    stringRedisTemplate.delete(KEY_PREFIX + name);
}

可是這里會存在一個隱患——假設該線程發(fā)生阻塞(或者其他問題),一直不釋放鎖(刪除 key)這可怎么辦?

為了解決這個問題,我們需要為 key 設計一個超時時間,讓它超時失效;但是這個超時時間的長短卻不好確定:

1、設置過短,會導致其他線程提前獲得鎖,引發(fā)線程安全問題。
2、設置過長,線程需要額外等待。

鎖的誤刪

 超時時間是一個非常不好把握的東西,因為業(yè)務線程的阻塞時間是不可預估的,在極端情況下,它總能阻塞到 lock 超時失效,正如上圖中的線程1,鎖超時釋放了,導致線程2也進來了,這時候 lock 是 線程2的鎖了(key 相同,value不同,value一般是線程唯一標識);假設這時候,線程1突然不阻塞了,它要釋放鎖,如果按照剛剛的代碼邏輯的話,它會釋放掉線程2的鎖;線程2的鎖被釋放掉之后,又會導致其他線程進來(線程3),如此往復。。。

為了解決這個問題,需要在釋放鎖時多加一個判斷,每個線程只釋放自己的鎖,不能釋放別人的鎖!

釋放鎖

@Override
public void unlock() {
    // 獲取線程標示
    String threadId = ID_PREFIX + Thread.currentThread().getId();
    // 獲取鎖中的標示
    String id = stringRedisTemplate.opsForValue().get(KEY_PREFIX + name);
    // 判斷標示是否一致
    if(threadId.equals(id)) {
        // 釋放鎖
        stringRedisTemplate.delete(KEY_PREFIX + name);
    }
}

原子性問題

剛剛我們談論的釋放鎖的邏輯:

1、判斷當前鎖是當前線程的鎖
2、當前線程釋放鎖
可以看到釋放鎖是分兩步完成的,如果你是對并發(fā)比較有感覺的話,應該一下子就知道這里會存在問題了。

分步執(zhí)行,并發(fā)問題!

假設 線程1 已經判斷當前鎖是它的鎖了,正準備釋放鎖,可偏偏這時候它阻塞了(可能是 FULL GC 引起的),鎖超時失效,線程2來加鎖,這時候鎖是線程2的了;可是如果線程1這時候醒過來,因為它已經執(zhí)行了步驟1了的,所以這時候它會直接直接步驟2,釋放鎖(可是此時的鎖不是線程1的了)

其實這就是一個原子性的問題,剛剛釋放鎖的兩步應該是原子的,不可分的!

要使得其滿足原子性,則需要在 Redis 中使用 Lua 腳本了。

引入 Lua 腳本保持原子性
lua 腳本:

-- 比較線程標示與鎖中的標示是否一致
if(redis.call('get', KEYS[1]) ==  ARGV[1]) then
    -- 釋放鎖 del key
    return redis.call('del', KEYS[1])
end
return 0

Java 中調用執(zhí)行:

public class SimpleRedisLock implements ILock {
?
    private String name;
    private StringRedisTemplate stringRedisTemplate;
?
    public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) {
        this.name = name;
        this.stringRedisTemplate = stringRedisTemplate;
    }
?
    private static final String KEY_PREFIX = "lock:";
    private static final String ID_PREFIX = UUID.randomUUID().toString(true) + "-";
    private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;
    static {
        UNLOCK_SCRIPT = new DefaultRedisScript<>();
        UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
        UNLOCK_SCRIPT.setResultType(Long.class);
    }
?
    @Override
    public boolean tryLock(long timeoutSec) {
        // 獲取線程標示
        String threadId = ID_PREFIX + Thread.currentThread().getId();
        // 獲取鎖
        Boolean success = stringRedisTemplate.opsForValue()
                .setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(success);
    }
?
    @Override
    public void unlock() {
        // 調用lua腳本
        stringRedisTemplate.execute(
                UNLOCK_SCRIPT,
                Collections.singletonList(KEY_PREFIX + name),
                ID_PREFIX + Thread.currentThread().getId());
    }
}

到了目前為止,我們設計的 Redis 分布式鎖已經是生產可用的,相對完善的分布式鎖了。

以上就是短視頻開發(fā),基于Redis的分布式鎖及原子性問題, 更多內容歡迎關注之后的文章

到此這篇關于短視頻開發(fā),基于Redis的分布式鎖及原子性問題的文章就介紹到這了,更多相關Redis的分布式鎖內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Redis 哨兵機制及配置實現(xiàn)

    Redis 哨兵機制及配置實現(xiàn)

    本文主要介紹了Redis 哨兵機制及配置實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 提高redis緩存命中率的方法

    提高redis緩存命中率的方法

    在本篇文章里小編給大家整理了關于怎么提高redis緩存命中率的相關知識點內容,有興趣的朋友們跟著學習下。
    2019-06-06
  • Redis底層類型之json命令使用

    Redis底層類型之json命令使用

    這篇文章主要為大家介紹了Redis底層類型之json命令使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • Windows環(huán)境下Redis Cluster環(huán)境搭建(圖文)

    Windows環(huán)境下Redis Cluster環(huán)境搭建(圖文)

    這篇文章主要介紹了Windows環(huán)境下Redis Cluster環(huán)境搭建(圖文),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • Redis?布隆過濾器命令的使用詳解

    Redis?布隆過濾器命令的使用詳解

    這篇文章主要介紹了Redis?布隆過濾器的相關命令的使用,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08
  • Redis本地/遠程(外部)連接失敗問題及解決

    Redis本地/遠程(外部)連接失敗問題及解決

    這篇文章主要介紹了Redis本地/遠程(外部)連接失敗問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • 淺談Redis變慢的原因及排查方法

    淺談Redis變慢的原因及排查方法

    本文主要介紹了淺談Redis變慢的原因及排查方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-06-06
  • 解決Redis啟動警告問題

    解決Redis啟動警告問題

    這篇文章介紹了解決Redis啟動警告問題的方法,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-02-02
  • Redis的哈希Hash類型常用命令的使用小結

    Redis的哈希Hash類型常用命令的使用小結

    Redis哈希類型類似于一個鍵值對集合,通常用于存儲對象,每個哈希包含多個字段,每個字段都有一個值,哈希類型支持一系列常用命令,下面就來詳細的介紹一下這些命令的使用,感興趣的可以了解一下
    2025-08-08
  • redis主從連接不成功錯誤問題及解決

    redis主從連接不成功錯誤問題及解決

    這篇文章主要介紹了redis主從連接不成功錯誤問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教<BR>
    2024-01-01

最新評論

资中县| 峨眉山市| 云安县| 佛坪县| 衡山县| 盐津县| 大丰市| 望城县| 浏阳市| 工布江达县| 浦北县| 克拉玛依市| 郎溪县| 郁南县| 安平县| 义马市| 弥勒县| 鄢陵县| 宜丰县| 富蕴县| 浦北县| 邳州市| 华宁县| 碌曲县| 吉林市| 宾阳县| 金山区| 勐海县| 石屏县| 宜君县| 松溪县| 巴中市| 宁化县| 克什克腾旗| 潞西市| 温州市| 重庆市| 津市市| 航空| 海淀区| 茶陵县|