溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Redis分布式Java鎖的應(yīng)用

發(fā)布時(shí)間:2020-06-17 14:58:02 來源:億速云 閱讀:168 作者:元一 欄目:編程語言

什么是分布式鎖?

分布式鎖是控制分布式系統(tǒng)之間同步訪問共享資源的一種方式。在分布式系統(tǒng)中,常常需要協(xié)調(diào)他們的動(dòng)作。如果不同的系統(tǒng)或是同一個(gè)系統(tǒng)的不同主機(jī)之間共享了一個(gè)或一組資源,那么訪問這些資源的時(shí)候,往往需要互斥來防止彼此干擾來保證一致性,在這種情況下,便需要使用到分布式鎖。

在Java中,由于多種原因,鎖定對象通常比使用同步塊更靈活。首先,Lock API可以以不同的方法運(yùn)行,而同步塊完全包含在一個(gè)方法中。
另外,如果線程被阻止,則無法訪問同步的塊。使用Lock,該線程將僅在可用時(shí)獲取鎖。這大大減少了線程等待的時(shí)間。另外,當(dāng)線程正在等待時(shí),可以調(diào)用一種方法來中斷線程,而當(dāng)線程正在等待獲取同步塊時(shí),這是不可能的。

分布式鎖定意味著你不僅需要考慮多個(gè)線程或進(jìn)程,還需要考慮在不同計(jì)算機(jī)上運(yùn)行的不同客戶端。這些單獨(dú)的服務(wù)器必須進(jìn)行協(xié)調(diào),以確保它們中的任何一個(gè)在任何給定時(shí)間都在使用資源。

Redis的分布式Java鎖定工具

Redisson框架是用于Java的基于Redis的內(nèi)存數(shù)據(jù)網(wǎng)格,可為需要執(zhí)行分布式鎖定的程序員提供多個(gè)對象。 下面,我們將討論每個(gè)選項(xiàng)及其之間的區(qū)別。

1.鎖

RLock接口在Java中實(shí)現(xiàn)java.util.concurrent.locks.Lock接口。 這是一個(gè)可重入鎖,這意味著線程可以多次鎖定資源。 一個(gè)計(jì)數(shù)器變量跟蹤鎖定請求被執(zhí)行了多少次。 一旦線程發(fā)出足夠的解鎖請求并且計(jì)數(shù)器達(dá)到0,資源便被釋放。

以下簡單代碼示例演示了如何在Redisson中創(chuàng)建和初始化Lock:

RLock lock = redisson.getLock("anyLock");
// Most familiar locking method
lock.lock();
try {
  ...
} finally {
  lock.unlock();
}

如果獲取此鎖的Redisson實(shí)例崩潰,則該鎖可能會(huì)在此獲取狀態(tài)下永久掛起。 為了避免這種情況,Redisson維護(hù)了一個(gè)鎖“看門狗”,該“看門狗”會(huì)在持有該鎖的Redisson實(shí)例仍處于活動(dòng)狀態(tài)時(shí)延長該鎖的過期時(shí)間。 默認(rèn)情況下,此鎖定看門狗的超時(shí)為30秒。 可以通過Config.lockWatchdogTimeout設(shè)置更改此限制。

Redisson還允許你在獲取租約時(shí)指定leaseTime參數(shù)。 在指定的時(shí)間間隔后,鎖將自動(dòng)釋放:

// Acquire lock and release it automatically after 10 seconds
// if unlock method hasn't been invoked
lock.lock(10, TimeUnit.SECONDS);
// Wait for 100 seconds and automatically unlock it after 10 seconds
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {
   try {
     ...
   } finally {
       lock.unlock();
   }
}

Redisson還為Lock對象提供了異步/響應(yīng)/ rxjava2接口:

RLock lock = redisson.getLock("anyLock");
lock.lockAsync();
...
// Reactive Stream (Spring Project Reactor implementation)
RLockReactive lock = redissonReactive.getLock("anyLock");
Mono<Void> res = lock.lock();
...
// Reactive Stream (RxJava2 implementation)
RLockReactive lock = redissonRx.getLock("anyLock");
Flowable<Void> res = lock.lock();
...

由于RLock實(shí)現(xiàn)了Lock接口,因此只有擁有鎖的線程才能解鎖資源。 否則,任何嘗試都會(huì)遇到IllegalMonitorStateException。

2. FairLock

與其表兄弟RLock一樣,RFairLock也實(shí)現(xiàn)了java.util.concurrent.locks.Lock接口。 通過使用FairLock,你可以保證線程將按照請求資源的順序來獲取資源(即``先進(jìn)先出''隊(duì)列)。 在為隊(duì)列中的下一個(gè)線程解鎖資源之前,Redisson會(huì)給已死掉五秒鐘的線程重新啟動(dòng)。

與RLocks一樣,創(chuàng)建和啟動(dòng)FairLock是一個(gè)簡單的過程:

RLock lock = redisson.getFairLock("anyLock");
lock.lock();
try {
  ...
} catch {
  lock.unlock();
}

3. RedLock

RedissonRedLock對象實(shí)現(xiàn)Redlock鎖定算法,以將分布式鎖與Redis一起使用:

RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");
RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
lock.lock();
try {
  ...
} finally {
   lock.unlock();
}

在Redlock算法中,我們在單獨(dú)的計(jì)算機(jī)或虛擬機(jī)上有許多獨(dú)立的Redis主節(jié)點(diǎn)。 該算法嘗試使用相同的鍵名和隨機(jī)值依次獲取這些實(shí)例中的每個(gè)實(shí)例的鎖。 僅當(dāng)客戶端能夠比鎖有效的總時(shí)間更快地從大多數(shù)實(shí)例中獲取鎖時(shí),才獲取鎖。

4.ReadWriteLock

Redisson的RReadWriteLock實(shí)現(xiàn)了java.util.concurrent.locks.ReadWriteLock接口。 在Java中,讀/寫鎖實(shí)際上是兩個(gè)鎖的組合:一個(gè)只讀鎖可以同時(shí)由多個(gè)線程擁有,而寫鎖只能一次由一個(gè)線程擁有。

創(chuàng)建和初始化RReadWriteLock的方法如下:

RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock");
rwlock.readLock().lock();
try {
  ...
} finally {
  rwlock.readLock().lock();
}
rwlock.writeLock().lock();
try {
  ...
} finally {
  rwlock.writeLock().lock();
}

5.多重鎖

RedissonMultiLock對象能夠?qū)⒍鄠€(gè)單獨(dú)的RLock實(shí)例組合在一起并作為單個(gè)實(shí)體進(jìn)行管理:

RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");
RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
lock.lock();
try {
  ...
} finally {
  lock.unlock();
}

正如我們在上面的示例中看到的那樣,每個(gè)RLock對象可能屬于不同的Redisson實(shí)例。 反過來,這可能會(huì)連接到其他Redis數(shù)據(jù)庫。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI