您好,登錄后才能下訂單哦!
什么是分布式鎖?
分布式鎖是控制分布式系統之間同步訪問共享資源的一種方式。在分布式系統中,常常需要協調他們的動作。如果不同的系統或是同一個系統的不同主機之間共享了一個或一組資源,那么訪問這些資源的時候,往往需要互斥來防止彼此干擾來保證一致性,在這種情況下,便需要使用到分布式鎖。
在Java中,由于多種原因,鎖定對象通常比使用同步塊更靈活。首先,Lock API可以以不同的方法運行,而同步塊完全包含在一個方法中。
另外,如果線程被阻止,則無法訪問同步的塊。使用Lock,該線程將僅在可用時獲取鎖。這大大減少了線程等待的時間。另外,當線程正在等待時,可以調用一種方法來中斷線程,而當線程正在等待獲取同步塊時,這是不可能的。
分布式鎖定意味著你不僅需要考慮多個線程或進程,還需要考慮在不同計算機上運行的不同客戶端。這些單獨的服務器必須進行協調,以確保它們中的任何一個在任何給定時間都在使用資源。
基Redis的分布式Java鎖定工具
Redisson框架是用于Java的基于Redis的內存數據網格,可為需要執行分布式鎖定的程序員提供多個對象。 下面,我們將討論每個選項及其之間的區別。
1.鎖
RLock接口在Java中實現java.util.concurrent.locks.Lock接口。 這是一個可重入鎖,這意味著線程可以多次鎖定資源。 一個計數器變量跟蹤鎖定請求被執行了多少次。 一旦線程發出足夠的解鎖請求并且計數器達到0,資源便被釋放。
以下簡單代碼示例演示了如何在Redisson中創建和初始化Lock:
RLock lock = redisson.getLock("anyLock");
// Most familiar locking method
lock.lock();
try {
...
} finally {
lock.unlock();
}
如果獲取此鎖的Redisson實例崩潰,則該鎖可能會在此獲取狀態下永久掛起。 為了避免這種情況,Redisson維護了一個鎖“看門狗”,該“看門狗”會在持有該鎖的Redisson實例仍處于活動狀態時延長該鎖的過期時間。 默認情況下,此鎖定看門狗的超時為30秒。 可以通過Config.lockWatchdogTimeout設置更改此限制。
Redisson還允許你在獲取租約時指定leaseTime參數。 在指定的時間間隔后,鎖將自動釋放:
// 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對象提供了異步/響應/ 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實現了Lock接口,因此只有擁有鎖的線程才能解鎖資源。 否則,任何嘗試都會遇到IllegalMonitorStateException。
2. FairLock
與其表兄弟RLock一樣,RFairLock也實現了java.util.concurrent.locks.Lock接口。 通過使用FairLock,你可以保證線程將按照請求資源的順序來獲取資源(即``先進先出''隊列)。 在為隊列中的下一個線程解鎖資源之前,Redisson會給已死掉五秒鐘的線程重新啟動。
與RLocks一樣,創建和啟動FairLock是一個簡單的過程:
RLock lock = redisson.getFairLock("anyLock");
lock.lock();
try {
...
} catch {
lock.unlock();
}
3. RedLock
RedissonRedLock對象實現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算法中,我們在單獨的計算機或虛擬機上有許多獨立的Redis主節點。 該算法嘗試使用相同的鍵名和隨機值依次獲取這些實例中的每個實例的鎖。 僅當客戶端能夠比鎖有效的總時間更快地從大多數實例中獲取鎖時,才獲取鎖。
4.ReadWriteLock
Redisson的RReadWriteLock實現了java.util.concurrent.locks.ReadWriteLock接口。 在Java中,讀/寫鎖實際上是兩個鎖的組合:一個只讀鎖可以同時由多個線程擁有,而寫鎖只能一次由一個線程擁有。
創建和初始化RReadWriteLock的方法如下:
RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock");
rwlock.readLock().lock();
try {
...
} finally {
rwlock.readLock().lock();
}
rwlock.writeLock().lock();
try {
...
} finally {
rwlock.writeLock().lock();
}
5.多重鎖
RedissonMultiLock對象能夠將多個單獨的RLock實例組合在一起并作為單個實體進行管理:
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();
}
正如我們在上面的示例中看到的那樣,每個RLock對象可能屬于不同的Redisson實例。 反過來,這可能會連接到其他Redis數據庫。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。