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

深入了解Redis的看門狗機(jī)制

 更新時(shí)間:2024年12月30日 11:06:49   作者:@Java小牛馬  
Redis鎖的延期機(jī)制,通常被稱為看門狗機(jī)制,本文就拉介紹一下Redis的看門狗機(jī)制,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

Redis鎖的延期機(jī)制,通常被稱為“看門狗”機(jī)制,是為了處理持有鎖的客戶端在執(zhí)行任務(wù)時(shí)發(fā)生崩潰或網(wǎng)絡(luò)分區(qū)等異常情況,導(dǎo)致鎖無法被釋放,從而避免死鎖的發(fā)生。

一、何為“看門狗”

看門狗機(jī)制的主要作用是自動(dòng)續(xù)期鎖,確保在節(jié)點(diǎn)完成任務(wù)之前,鎖不會(huì)過期。具體來說,當(dāng)一個(gè)節(jié)點(diǎn)獲取到鎖后,看門狗會(huì)定期檢查該鎖的過期時(shí)間,并在必要時(shí)延長(zhǎng)鎖的過期時(shí)間,確保節(jié)點(diǎn)可以順利完成任務(wù)。

二、分析

以下是Redisson看門狗機(jī)制的核心代碼片段:

// 初始化看門狗線程
private void startWatchdog() {
    // 每隔10秒檢查一次鎖的狀態(tài)
    long delay = 10 * 1000;
    watchdogFuture = scheduler.scheduleWithFixedDelay(() -> {
        try {
            // 檢查當(dāng)前持有的鎖
            checkAndExtendLocks();
        } catch (Exception e) {
            // 處理異常
            handleWatchdogException(e);
        }
    }, delay, delay, TimeUnit.MILLISECONDS);
}

// 檢查并延長(zhǎng)鎖的過期時(shí)間
private void checkAndExtendLocks() {
    for (RLock lock : locks) {
        if (lock.isHeldByCurrentThread()) {
            // 更新鎖的過期時(shí)間
            lock.extendLeaseTime();
        }
    }
}

// 更新鎖的過期時(shí)間
private void extendLeaseTime() {
    String script = "if redis.call('exists', KEYS[1]) == 1 then " +
                    "redis.call('pexpire', KEYS[1], ARGV[1]); " +
                    "return 1; " +
                    "else " +
                    "return 0; " +
                    "end";
    // 執(zhí)行Redis腳本,更新鎖的過期時(shí)間
    redisTemplate.execute(new DefaultRedisScript<>(script, Integer.class), Collections.singletonList(lockKey), leaseTime);
}

在上述代碼中,startWatchdog方法啟動(dòng)了一個(gè)定時(shí)任務(wù),每隔10秒檢查一次當(dāng)前持有的鎖,并調(diào)用checkAndExtendLocks方法延長(zhǎng)鎖的過期時(shí)間。extendLeaseTime方法通過執(zhí)行Redis腳本來更新鎖的過期時(shí)間,確保鎖在任務(wù)完成之前不會(huì)過期。

tryLock方法的源碼解讀
Redisson中的tryLock方法是獲取鎖的核心方法之一,提供了非阻塞的嘗試獲取鎖的功能。以下是tryLock方法的核心實(shí)現(xiàn)及其源碼解讀。

tryLock方法的核心代碼

@Override
public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
    long time = unit.toMillis(waitTime);
    long leaseTimeInMillis = unit.toMillis(leaseTime);
    long currentTime = System.currentTimeMillis();
    long lockExpireTime = currentTime + leaseTimeInMillis;

    String lockValue = UUID.randomUUID().toString();
    boolean acquired = tryAcquireLock(lockValue, leaseTimeInMillis);

    if (!acquired && time > 0) {
        long endTime = currentTime + time;
        while (System.currentTimeMillis() < endTime) {
            acquired = tryAcquireLock(lockValue, leaseTimeInMillis);
            if (acquired) {
                break;
            }
            Thread.sleep(10); // Retry interval
        }
    }

    if (acquired) {
        scheduleExpirationRenewal(lockValue, leaseTimeInMillis);
    }

    return acquired;
}

在這段代碼中,tryLock方法嘗試在指定的等待時(shí)間內(nèi)獲取鎖,并設(shè)置鎖的過期時(shí)間。方法參數(shù)包括:

waitTime:等待時(shí)間,即在超時(shí)前持續(xù)嘗試獲取鎖的時(shí)間。
leaseTime:鎖的過期時(shí)間。
unit:時(shí)間單位。
tryAcquireLock方法:tryAcquireLock方法嘗試實(shí)際獲取鎖,如果成功則返回true。

private boolean tryAcquireLock(String lockValue, long leaseTimeInMillis) {
    String script = "if redis.call('setnx', KEYS[1], ARGV[1]) == 1 then " +
                    "redis.call('pexpire', KEYS[1], ARGV[2]); " +
                    "return 1; " +
                    "else " +
                    "return 0; " +
                    "end";
    List<Object> keys = Collections.singletonList(lockKey);
    List<Object> args = Arrays.asList(lockValue, leaseTimeInMillis);
    Long result = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), keys, args);

    return result != null && result == 1;
}

該方法執(zhí)行Lua腳本:

使用setnx命令嘗試設(shè)置鎖的鍵值對(duì),如果成功則返回1。
使用pexpire命令設(shè)置鎖的過期時(shí)間。
scheduleExpirationRenewal方法
如果鎖獲取成功,scheduleExpirationRenewal方法會(huì)啟動(dòng)一個(gè)看門狗線程來自動(dòng)延長(zhǎng)鎖的過期時(shí)間。

private void scheduleExpirationRenewal(String lockValue, long leaseTimeInMillis) {
    long delay = leaseTimeInMillis / 3;
    scheduler.scheduleWithFixedDelay(() -> {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                        "redis.call('pexpire', KEYS[1], ARGV[2]); " +
                        "end";
        List<Object> keys = Collections.singletonList(lockKey);
        List<Object> args = Arrays.asList(lockValue, leaseTimeInMillis);
        redisTemplate.execute(new DefaultRedisScript<>(script, Void.class), keys, args);
    }, delay, delay, TimeUnit.MILLISECONDS);
}

這個(gè)方法啟動(dòng)一個(gè)定時(shí)任務(wù),每隔leaseTimeInMillis / 3的時(shí)間間隔,檢查鎖是否仍然由當(dāng)前線程持有,如果是,則延長(zhǎng)其過期時(shí)間。

關(guān)鍵點(diǎn)總結(jié)tryLock方法提供了非阻塞的嘗試獲取鎖的功能,允許在指定的時(shí)間內(nèi)多次嘗試獲取鎖。
tryAcquireLock方法執(zhí)行Lua腳本,使用Redis命令setnx和pexpire來實(shí)現(xiàn)鎖的獲取和過期時(shí)間設(shè)置。
scheduleExpirationRenewal方法啟動(dòng)一個(gè)定時(shí)任務(wù),通過Lua腳本自動(dòng)延長(zhǎng)鎖的過期時(shí)間,以防止鎖在任務(wù)完成前過期。

通過上述代碼和解析,我們可以更清楚地理解Redisson中tryLock方法的工作原理以及其在分布式鎖管理中的作用。

看門狗機(jī)制的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

自動(dòng)續(xù)期:看門狗機(jī)制可以自動(dòng)續(xù)期鎖,確保任務(wù)在完成之前鎖不會(huì)過期。
可靠性高:通過定期檢查鎖的狀態(tài),看門狗機(jī)制可以確保鎖的持有狀態(tài),從而提高系統(tǒng)的可靠性。

缺點(diǎn):

資源消耗:看門狗機(jī)制需要后臺(tái)線程定期檢查鎖的狀態(tài),這會(huì)消耗一定的系統(tǒng)資源。
復(fù)雜性增加:看門狗機(jī)制的引入增加了系統(tǒng)的復(fù)雜性,可能需要額外的調(diào)試和維護(hù)工作。

看門狗機(jī)制的優(yōu)化

在使用Redisson的看門狗機(jī)制時(shí),針對(duì)具體的應(yīng)用場(chǎng)景和系統(tǒng)需求,可以進(jìn)行以下優(yōu)化: 合理設(shè)置檢查頻率:根據(jù)任務(wù)的執(zhí)行時(shí)間和系統(tǒng)的負(fù)載情況,合理設(shè)置看門狗線程的檢查頻率,既保證鎖的持有狀態(tài),又減少系統(tǒng)資源的消耗。 優(yōu)化Redis腳本:使用高效的Redis腳本來更新鎖的過期時(shí)間,減少Redis服務(wù)器的負(fù)載。 監(jiān)控和報(bào)警:建立完善的監(jiān)控和報(bào)警機(jī)制,及時(shí)發(fā)現(xiàn)和處理看門狗機(jī)制中的異常情況,確保系統(tǒng)的穩(wěn)定性。

三、案例實(shí)踐

案例1:訂單處理系統(tǒng)中的看門狗機(jī)制優(yōu)化

場(chǎng)景描述

在一個(gè)大型電商平臺(tái)的訂單處理系統(tǒng)中,訂單處理可能需要較長(zhǎng)時(shí)間。為了確保分布式鎖在處理過程中不會(huì)過期,系統(tǒng)啟用了Redisson的看門狗機(jī)制。然而,由于系統(tǒng)負(fù)載較高,看門狗線程的頻繁檢查導(dǎo)致了系統(tǒng)資源消耗問題。

解決方案

合理設(shè)置檢查頻率:通過調(diào)整Redisson配置,降低看門狗線程的檢查頻率,以減少系統(tǒng)資源消耗。

Config config = new Config();
config.useSingleServer()
      .setAddress("redis://127.0.0.1:6379")
      .setWatchdogTimeout(30000); // 將看門狗超時(shí)時(shí)間設(shè)置為30秒
RedissonClient redissonClient = Redisson.create(config);

2.優(yōu)化Redis腳本:使用Lua腳本來更新鎖的過期時(shí)間,減少Redis服務(wù)器的負(fù)載。

String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                "return redis.call('expire', KEYS[1], ARGV[2]) " +
                "else return 0 end";
redisClient.eval(script, Collections.singletonList("myLock"), Arrays.asList("lockValue", "30"));

3.監(jiān)控和報(bào)警:建立監(jiān)控和報(bào)警機(jī)制,及時(shí)發(fā)現(xiàn)和處理看門狗機(jī)制中的異常情況。

// 示例:使用Prometheus進(jìn)行監(jiān)控
@Autowired
private MeterRegistry meterRegistry;

public void monitorWatchdog() {
    meterRegistry.gauge("redisson_watchdog_status", redissonClient.getLock("myLock").isLocked() ? 1 : 0);
}

案例2:數(shù)據(jù)處理任務(wù)中的看門狗機(jī)制優(yōu)化

場(chǎng)景描述

在一個(gè)數(shù)據(jù)處理系統(tǒng)中,每個(gè)任務(wù)可能需要幾分鐘甚至更長(zhǎng)的時(shí)間才能完成。如果看門狗線程因故停止工作,可能導(dǎo)致鎖過期,導(dǎo)致數(shù)據(jù)不一致問題。

解決方案

引入備用線程:增加備用線程來監(jiān)控看門狗線程的狀態(tài),如果發(fā)現(xiàn)看門狗線程停止工作,立即啟動(dòng)備用線程進(jìn)行處理。

public class WatchdogBackup implements Runnable {
    private final RedissonClient redissonClient;

    public WatchdogBackup(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    @Override
    public void run() {
        RLock lock = redissonClient.getLock("myLock");
        while (true) {
            if (!lock.isLocked()) {
                System.out.println("Watchdog stopped, acquiring lock...");
                lock.lock();
            }
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

public void startBackupWatchdog(RedissonClient redissonClient) {
    Thread backupThread = new Thread(new WatchdogBackup(redissonClient));
    backupThread.setDaemon(true);
    backupThread.start();
}

2.冗余機(jī)制:設(shè)置多個(gè)看門狗線程,以提高系統(tǒng)的可靠性。

public void startRedundantWatchdogs(RedissonClient redissonClient) {
    for (int i = 0; i < 3; i++) {
        Thread watchdogThread = new Thread(new WatchdogBackup(redissonClient));
        watchdogThread.setDaemon(true);
        watchdogThread.start();
    }
}

通過這些優(yōu)化措施,我們可以有效地提高看門狗機(jī)制的可靠性和效率,確保在長(zhǎng)時(shí)間任務(wù)執(zhí)行過程中鎖不會(huì)過期,從而避免數(shù)據(jù)不一致和系統(tǒng)資源消耗問題。

到此這篇關(guān)于深入了解Redis的看門狗機(jī)制的文章就介紹到這了,更多相關(guān)Redis 看門狗機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis中scan命令的深入講解

    Redis中scan命令的深入講解

    這篇文章主要給大家介紹了關(guān)于Redis中scan命令的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用redis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-10-10
  • Ubuntu系統(tǒng)中Redis的安裝步驟及服務(wù)配置詳解

    Ubuntu系統(tǒng)中Redis的安裝步驟及服務(wù)配置詳解

    本文主要記錄了Ubuntu服務(wù)器中Redis服務(wù)的安裝使用,包括apt安裝和解壓縮編譯安裝兩種方式,并對(duì)安裝過程中可能出現(xiàn)的問題、解決方案進(jìn)行說明,以及在手動(dòng)安裝時(shí),服務(wù)器如何添加自定義服務(wù)的問題,需要的朋友可以參考下
    2024-12-12
  • 使用Redis獲取數(shù)據(jù)轉(zhuǎn)json,解決動(dòng)態(tài)泛型傳參的問題

    使用Redis獲取數(shù)據(jù)轉(zhuǎn)json,解決動(dòng)態(tài)泛型傳參的問題

    這篇文章主要介紹了使用Redis獲取數(shù)據(jù)轉(zhuǎn)json,解決動(dòng)態(tài)泛型傳參的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • Redis+IDEA實(shí)現(xiàn)單機(jī)鎖和分布式鎖的過程

    Redis+IDEA實(shí)現(xiàn)單機(jī)鎖和分布式鎖的過程

    這篇文章主要介紹了Redis+IDEA實(shí)現(xiàn)單機(jī)鎖和分布式鎖的過程,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • 一文快速搞懂Redis的幾種數(shù)據(jù)類型方式

    一文快速搞懂Redis的幾種數(shù)據(jù)類型方式

    這篇文章主要介紹了一文快速搞懂Redis的幾種數(shù)據(jù)類型方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • kubernetes環(huán)境部署單節(jié)點(diǎn)redis數(shù)據(jù)庫的方法

    kubernetes環(huán)境部署單節(jié)點(diǎn)redis數(shù)據(jù)庫的方法

    這篇文章主要介紹了kubernetes環(huán)境部署單節(jié)點(diǎn)redis數(shù)據(jù)庫的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • 解讀redis?slaveof命令執(zhí)行后為什么需要清庫重新同步

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

    這篇文章主要介紹了redis?slaveof命令執(zhí)行后為什么需要清庫重新同步,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • Redis都做了哪些加快速度的設(shè)計(jì)

    Redis都做了哪些加快速度的設(shè)計(jì)

    這篇文章主要介紹了Redis都做了哪些加快速度的設(shè)計(jì)的相關(guān)資料,需要的朋友可以參考下
    2021-02-02
  • 高并發(fā)場(chǎng)景分析之redis+lua防重校驗(yàn)

    高并發(fā)場(chǎng)景分析之redis+lua防重校驗(yàn)

    這篇文章主要介紹了高并發(fā)場(chǎng)景分析之redis+lua防重校驗(yàn),本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • Redis數(shù)據(jù)庫的鍵管理示例詳解

    Redis數(shù)據(jù)庫的鍵管理示例詳解

    這篇文章主要為大家介紹了Redis數(shù)據(jù)庫的鍵管理示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10

最新評(píng)論