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

Redis分布式鎖的幾種實(shí)現(xiàn)方法

 更新時間:2025年04月16日 08:25:21   作者:今天多喝熱水  
本文主要介紹了Redis分布式鎖的幾種實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

Redis基本命令:

// 設(shè)置鍵myKey的值為myValue,并且該鍵在10秒后過期
SET myKey myValue EX 10
// 設(shè)置鍵myKey的值為myValue,并且該鍵在1000毫秒(1秒)后過期
SET myKey myValue PX 1000
// 指定key過期時間,單位是秒,過期后自動刪除
EXPIRE key_name second_num
// 指定key過期時間,單位是毫秒,過期后自動刪除
PEXPIRE key_name millisecond_num

// 返回key過期時間
TTL key_name 

SET key value	 //設(shè)置鍵key的值為value
SETNX key value	 //只有在鍵key不存在的情況下,將key的值設(shè)置為value
SETEX key seconds value	 //將鍵key的值設(shè)置為value,并且超時時間為seconds秒
PSETEX key milliseconds value  //將鍵key的值設(shè)置為value,并且超時時間為milliseconds毫秒

一、基礎(chǔ)方案:SETNX命令實(shí)現(xiàn)

public class SimpleRedisLock {
    private Jedis jedis;
    private String lockKey;

    public SimpleRedisLock(Jedis jedis, String lockKey) {
        this.jedis = jedis;
        this.lockKey = lockKey;
    }
    public boolean tryLock() {
        Long result = jedis.setnx(lockKey, "locked");
        if (result == 1) {
            jedis.expire(lockKey, 30); // 設(shè)置過期時間
            return true;
        }
        return false;
    }
    public void unlock() {
        jedis.del(lockKey);
    }
}

// 使用示例
Jedis jedis = new Jedis("localhost");
SimpleRedisLock lock = new SimpleRedisLock(jedis, "order_lock");
try{
    if(lock.tryLock()){
    // 業(yè)務(wù)邏輯
    }
} finally {
    lock.unlock();
}

問題分析:

  • 非原子操作:setnx和expire非原子操作,可能產(chǎn)生死鎖
  • 鎖誤刪:任何客戶端都可以刪除鎖
  • 不可重入:同一線程重復(fù)獲取會失敗

二、改進(jìn)方案:原子SET命令

public class AtomicRedisLock {
    private Jedis jedis;
    private String lockKey;
    private String clientId;

    public SimpleRedisLock(Jedis jedis, String lockKey) {
        this.jedis = jedis;
        this.lockKey = lockKey;
        this.clientId = UUID.randomUUID().toString();
    }
    public boolean tryLock(int expireSeconds) {
        String result = jedis.set(lockKey, clientId, SetParams.setParams().nx().ex(expireSeconds));
        return "OK".equals(result);
    }
    public boolean unlock() {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                "return redis.call('del', KEYS[1]) " +
                "else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(clientId));
        return result.equals(1L);
    }
}

// 使用示例
Jedis jedis = new Jedis("localhost");
AtomicRedisLock lock = new AtomicRedisLock(jedis, "payment_lock");
try{
    if(lock.tryLock(30)){
    // 業(yè)務(wù)邏輯
    }
} finally {
    lock.unlock();
}

核心改進(jìn):

  • 使用原子SET命令:SET key value NX EX
  • Lua腳本保證刪除原子性
  • 客戶端唯一標(biāo)識防止誤刪

仍然存在的問題:

  • 鎖續(xù)期困難
  • 單點(diǎn)故障風(fēng)險
  • 業(yè)務(wù)超時可能導(dǎo)致鎖失效

三、高可用方案:RedLock算法

public class RedLock {
    pprivate List<Jedis> jedisList;
    private String lockKey;
    private String clientId;
    private int quorum;

    public RedLock(List<Jedis> jedisList, String lockKey) {
        this.jedisList = jedisList;
        this.lockKey = lockKey;
        this.clientId = UUID.randomUUID().toString();
        this.quorum = jedisList.size() / 2 + 1;
    }
    public boolean tryLock(int expireMillis) {
        long startTime = System.currentTimeMillis();
        // 第一階段:嘗試獲取多數(shù)節(jié)點(diǎn)鎖
        int successCount = 0;
        for (Jedis jedis : jedisList) {
            if (tryAcquire(jedis, expireMillis)) {
                successCount++;
            }
            if ((System.currentTimeMillis() - startTime) > expireMillis) {
                break;
            }
        }
        // 第二階段:驗(yàn)證鎖有效性
        if (successCount >= quorum) {
            long validityTime = expireMillis - (System.currentTimeMillis() - startTime);
            return validityTime > 0;
        }
        // 第三階段:釋放已獲得的鎖
        for (Jedis jedis : jedisList) {
            release(jedis);
        }
        return false;
    }
    private boolean tryAcquire(Jedis jedis, long expireMillis) {
        try {
            String result = jedis.set(lockKey, clientId, SetParams.setParams().nx().px(expireMillis));
            return "OK".equals(result);
        } catch (Exception e) {
            return false;
        }
    }
    private void release(Jedis jedis) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                "return redis.call('del', KEYS[1]) else return 0 end";
        jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(clientId));
    }
}

部署要求:

  • 至少5個獨(dú)立Redis實(shí)例
  • 節(jié)點(diǎn)間時鐘同步
  • 需要配置合理的超時時間

適用場景:

  • 金融交易等對可靠性要求極高的場景
  • 需要跨機(jī)房部署的分布式系統(tǒng)

四、生產(chǎn)級方案:Redisson實(shí)現(xiàn)

// 配置Redisson客戶端
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
RedissonClient redisson = Redisson.create(config);
// 獲取鎖對象
RLock lock = redisson.getLock("orderLock");
try {
    // 嘗試加鎖,最多等待100秒,鎖定后30秒自動解鎖
    boolean isLock = lock.tryLock(100, 30, TimeUnit.SECONDS);
    if (isLock) {
        // 處理業(yè)務(wù)
    }
} finally {
    lock.unlock();
}

// 關(guān)閉客戶端
redisson.shutdown();
// 自動續(xù)期機(jī)制(Watchdog),Watchdog實(shí)現(xiàn)原理(簡化版)
private void renewExpiration() {
    Timeout task = commandExecutor.schedule(() -> {
        if (redisClient.eval(...)){ // 檢查是否仍持有鎖
            expireAsync(); // 續(xù)期
            renewExpiration(); // 遞歸調(diào)用
        }
    }, internalLockLeaseTime / 3, TimeUnit.MILLISECONDS);
}

核心特性:

  • 支持可重入鎖
  • 提供公平鎖、聯(lián)鎖(MultiLock)、紅鎖(RedLock)實(shí)現(xiàn)
  • 完善的故障處理機(jī)制

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

相關(guān)文章

  • spring?boot集成redis基礎(chǔ)入門實(shí)例詳解

    spring?boot集成redis基礎(chǔ)入門實(shí)例詳解

    redis在spring?boot項(xiàng)目開發(fā)中是常用的緩存套件,常見使用的是spring-boot-starter-data-redis,這篇文章主要介紹了spring?boot集成redis基礎(chǔ)入門,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-10-10
  • redis cluster集群模式下實(shí)現(xiàn)批量可重入鎖

    redis cluster集群模式下實(shí)現(xiàn)批量可重入鎖

    本文主要介紹了使用redis cluster集群版所遇到的問題解決方案及redis可重入鎖是否會有死鎖的問題等,具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • Redis?數(shù)據(jù)恢復(fù)及持久化策略分析

    Redis?數(shù)據(jù)恢復(fù)及持久化策略分析

    本文將詳細(xì)分析Redis的數(shù)據(jù)恢復(fù)機(jī)制,持久化策略及其特點(diǎn),并討論選擇持久化策略時需要考慮的因素,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • Redis內(nèi)存碎片處理實(shí)例詳解

    Redis內(nèi)存碎片處理實(shí)例詳解

    內(nèi)存碎片是redis服務(wù)中分配器分配存儲對象內(nèi)存的時產(chǎn)生的,下面這篇文章主要給大家介紹了關(guān)于Redis內(nèi)存碎片處理的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-05-05
  • Redis key命令key的儲存方式

    Redis key命令key的儲存方式

    這篇文章主要介紹了Redis key命令key的儲存方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • 解讀redis?slaveof命令執(zhí)行后為什么需要清庫重新同步

    解讀redis?slaveof命令執(zhí)行后為什么需要清庫重新同步

    這篇文章主要介紹了redis?slaveof命令執(zhí)行后為什么需要清庫重新同步,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • 面試常問:如何保證Redis緩存和數(shù)據(jù)庫的數(shù)據(jù)一致性

    面試常問:如何保證Redis緩存和數(shù)據(jù)庫的數(shù)據(jù)一致性

    在實(shí)際開發(fā)過程中,緩存的使用頻率是非常高的,只要使用緩存和數(shù)據(jù)庫存儲,就難免會出現(xiàn)雙寫時數(shù)據(jù)一致性的問題,那我們又該如何解決呢
    2021-09-09
  • linux?redis-連接命令解讀

    linux?redis-連接命令解讀

    這篇文章主要介紹了linux?redis-連接命令解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • springmvc集成使用redis過程

    springmvc集成使用redis過程

    這篇文章主要介紹了springmvc集成使用redis過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Redis SETEX命令實(shí)現(xiàn)鍵值對管理

    Redis SETEX命令實(shí)現(xiàn)鍵值對管理

    本文主要介紹了Redis SETEX命令實(shí)現(xiàn)鍵值對管理,SETEX命令用于設(shè)置具有過期時間的鍵值對,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06

最新評論