欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Redis對批量數(shù)據(jù)實現(xiàn)分布式鎖的實現(xiàn)代碼

 更新時間:2022年03月24日 09:46:10   作者:HCAN  
為了防止多人多電腦同時操作一條數(shù)據(jù),我們自己開發(fā)了一個簡單的基于Redis實現(xiàn)的分布式鎖,Redis對批量數(shù)據(jù)實現(xiàn)分布式鎖相關知識感興趣的朋友一起看看吧

需求背景

在開發(fā)的收入結(jié)轉(zhuǎn)平臺界面上有一個歸集按鈕,可以實現(xiàn)抓取結(jié)轉(zhuǎn)表里面的多條數(shù)據(jù)進行歸集操作。為了防止多人多電腦同時操作一條數(shù)據(jù),我們自己開發(fā)了一個簡單的基于Redis實現(xiàn)的分布式鎖。

代碼實現(xiàn)

邏輯代碼中的使用案例

參數(shù)說明:

scIds:結(jié)轉(zhuǎn)數(shù)據(jù)的ID主鍵集合。

timeOutToDeleteRedisKey:最大鎖超時時間(用于自動解鎖)

organizationId:租戶ID(這個參數(shù)根據(jù)情況選擇是否需要)

ReturnLock returnLock = RedisLock.applyByIds(scIds, redisLockTime, organizationId, () -> {
    // dothing 具體的代碼業(yè)務邏輯
    return 123;
});
 
if (!returnLock.getFlag()) {
    if(returnLock.getLock()){
        throw new CommonException("歸集數(shù)據(jù)有程序正在運行,請稍候刷新頁面重試");
    }else {
        throw new CommonException(returnLock.getErrorMsg());
    }
}
// 返回對象
System.out.println(returnLock.getResObj()) // 123

Redis加鎖方法封裝

public static ReturnLock applyByIds(List<Long> scIds, Long timeOutToDeleteRedisKey, Long tenantId,
                                    Supplier<Object> supplier) {
    // 獲得鎖
    Map<String, String> keyMap = getLockByIds(scIds, timeOutToDeleteRedisKey, tenantId);
    ReturnLock returnLock = new ReturnLock();
    returnLock.setFlag(true);
    returnLock.setLock(false);
    try {
        // 判斷主鍵ID數(shù)量和加鎖的數(shù)量是否一致,不一致說明有加鎖失敗的數(shù)據(jù),返回失敗鎖信息
        if(scIds.size() > keyMap.size()){
            returnLock.setFlag(false);
            returnLock.setLock(true);
            returnLock.setKeyMap(keyMap);
            return returnLock;
        }
        // 應用代碼執(zhí)行后的返回結(jié)果 supplier:java8四大內(nèi)置函數(shù)的供給型接口
        // Supplier<T>(供給型接口)無參數(shù),返回類型為T的對象:T get()
        returnLock.setResObj(supplier.get());
    }catch (Exception e) {
        returnLock.setFlag(false);
        returnLock.setErrorMsg(e.getMessage());
        e.printStackTrace();
    }finally {
        // 應用代碼執(zhí)行報錯,解鎖
        unLockByIds(keyMap);
    }
    return returnLock;
}

getLockByIds

批量獲取每一條數(shù)據(jù)的Redis鎖

private static Map<String, String> getLockByIds(List<Long> scIds, Long timeOutToDeleteRedisKey, Long tenantId) {
    Map<String, String> keyMap = new HashMap<>();
    // 從spring上下文中獲取Redis的操作對象,因為這個代碼是寫在util中,所以通過上下文方式獲取bean對象
    // RedisHelper:Redis的操作對象,我們自己公司基于redisTemplate封裝的
    RedisHelper redisHelper = SpringUtil.getBean(RedisHelper.class);
    try {
        if (CollectionUtil.isNotEmpty(scIds)) {
            for (int i = 0; i < scIds.size(); i++) {
                String item = "L_" + scIds.get(i);
                String UUID = UUIDUtils.generateTenantUUID(tenantId);
                // 判斷key值是否被鎖,如果沒有鎖則加鎖并設置過期時間, 如果有鎖, 則報錯并立即釋放已加的鎖
                // strSetIfAbsent會返回true/false,底層是封裝了java的setIfAbsent方法和Redis的setnx方法
                // 如果設置成功返回true否則false
                if (redisHelper.strSetIfAbsent(item, UUID)) {
                    // 設置過期時間
                    redisHelper.setExpire(item, timeOutToDeleteRedisKey, TimeUnit.SECONDS);
                    // 保存設置的鎖信息
                    keyMap.put(item, UUID);
                } else {
                    // 鎖設置異常,表示有數(shù)據(jù)被鎖住了,解鎖之間加鎖的數(shù)據(jù)
                    if (MapUtil.isNotEmpty(keyMap)) {
                        if (unLockByIds(keyMap)) {
                            // 解鎖失敗再次解鎖
                            unLockByIds(keyMap);
                        }
                    }
                    // 返回鎖信息
                    return keyMap;
                }
            }
        }
        return keyMap;
    }catch (Exception e) {
        e.printStackTrace();
    }
}

解鎖

private static Boolean unLockByIds(Map<String, String> keyMap) {
    RedisHelper redisHelper = SpringUtil.getBean(RedisHelper.class);
    try {
        if (MapUtil.isEmpty(keyMap)) {
            return false;
        }
        // 判斷是否是自己的鎖
        for (String key : keyMap.keySet()) {
            String uuid = keyMap.get(key);
            if (StringUtils.equals(uuid, redisHelper.strGet(key))) {
                // 封裝了redisTemplate.delete(key);
                redisHelper.delKey(key);
            }
        return true;
    }catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

實現(xiàn)效果

當對數(shù)據(jù)進行批量加鎖的時候,若在加鎖的過程中出現(xiàn)加鎖失敗,則回滾直接加的鎖,并提示"歸集數(shù)據(jù)有程序正在運行,請稍候刷新頁面重試"。

若業(yè)務代碼邏輯執(zhí)行成功或者執(zhí)行報錯都會自動的解鎖當前加鎖的數(shù)據(jù)。

到此這篇關于利用Redis對批量數(shù)據(jù)實現(xiàn)分布式鎖的文章就介紹到這了,更多相關Redis分布式鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 控制Redis的hash的field中的過期時間

    控制Redis的hash的field中的過期時間

    這篇文章主要介紹了控制Redis的hash的field中的過期時間問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • redis實現(xiàn)簡單隊列

    redis實現(xiàn)簡單隊列

    這篇文章主要為大家詳細介紹了redis實現(xiàn)簡單隊列的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • Redis 徹底禁用RDB持久化操作

    Redis 徹底禁用RDB持久化操作

    這篇文章主要介紹了Redis 徹底禁用RDB持久化的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 基于Redis延遲隊列的實現(xiàn)代碼

    基于Redis延遲隊列的實現(xiàn)代碼

    在生活中很多時候都會用到延遲隊列,本文基于Redis延遲隊列的實現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • redis配置文件中常用配置詳解

    redis配置文件中常用配置詳解

    這篇文章主要介紹了redis配置文件中常用配置詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • 詳解Redis緩存與Mysql如何保證雙寫一致

    詳解Redis緩存與Mysql如何保證雙寫一致

    緩存和數(shù)據(jù)庫如何保證數(shù)據(jù)的一致是個很經(jīng)典的問題,這篇文章就來和大家一起探討一下Redis緩存與Mysql如何保證雙寫一致,感興趣的小伙伴可以參考下
    2023-12-12
  • 一文弄懂Redis 線程模型

    一文弄懂Redis 線程模型

    使用Redis 時,幾乎不存在 CPU 成為瓶頸的情況, Redis 主要受限于內(nèi)存和網(wǎng)絡 使用了單線程后,可維護性高,感興趣的可以了解一下
    2024-02-02
  • 淺談Redis?中的過期刪除策略和內(nèi)存淘汰機制

    淺談Redis?中的過期刪除策略和內(nèi)存淘汰機制

    本文主要介紹了Redis?中的過期刪除策略和內(nèi)存淘汰機制,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-04-04
  • redis輕松處理經(jīng)緯度坐標點數(shù)據(jù)的實現(xiàn)方法

    redis輕松處理經(jīng)緯度坐標點數(shù)據(jù)的實現(xiàn)方法

    這篇文章主要介紹了redis輕松處理經(jīng)緯度坐標點數(shù)據(jù)的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • redis緩存的簡單操作(get、put)

    redis緩存的簡單操作(get、put)

    這篇文章主要介紹了redis緩存的簡單操作,包括引入jedisjar包、配置redis、RedisDao需要的一些工具等,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-09-09

最新評論