分散式鎖

在許多情況下,對某個上下文(甚至是單個訊息)執行的操作必須以獨佔方式進行。一個例子是聚合器元件,我們必須檢查當前訊息的訊息組狀態,以確定是釋放組還是僅將該訊息新增到將來考慮。為此,Java 提供了一個帶有 java.util.concurrent.locks.Lock 實現的 API。然而,當應用程式是分散式的和/或在叢集中執行時,問題變得更加複雜。在這種情況下,鎖定具有挑戰性,需要一些共享狀態及其特定的方法來實現排他性要求。

Spring Integration 提供了一個 LockRegistry 抽象,其記憶體中的 DefaultLockRegistry 實現基於 ReentrantLock API。LockRegistryobtain(Object) 方法需要一個用於特定上下文的 lock key。例如,聚合器使用 correlationKey 來鎖定其組周圍的操作。這樣,不同的鎖可以併發使用。此 obtain(Object) 方法返回一個 java.util.concurrent.locks.Lock 例項(取決於 LockRegistry 實現),因此,其餘邏輯與標準 Java 併發演算法相同。

從版本 6.2 開始,LockRegistry 提供了 executeLocked() API(此介面中的 default 方法)以在鎖定狀態下執行某些任務。此 API 的行為類似於眾所周知的 JdbcTemplateJmsTemplateRestTemplate。以下示例演示了此 API 的用法

LockRegistry registry = new DefaultLockRegistry();
...
registry.executeLocked("someLockKey", () -> someExclusiveResourceCall());

該方法重新丟擲任務呼叫中的異常,如果 Lock 被中斷,則丟擲 InterruptedException。此外,帶有 Duration 的變體在 lock.tryLock() 返回 false 時丟擲 java.util.concurrent.TimeoutException

Spring Integration 為分散式鎖提供了以下 LockRegistry 實現

Spring Cloud AWS 還提供了 DynamoDbLockRegistry

從版本 7.0 開始,引入了 DistributedLock 介面,提供了新方法 lock(Duration ttl)tryLock(long time, TimeUnit unit, Duration ttl),用於獲取具有自定義生存時間 (TTL) 的鎖。JdbcLockRedisLock 都實現了 DistributedLock 介面以支援自定義生存時間功能。LockRegistry<L extends Lock> 現在是擴充套件 Lock 的型別的通用介面。RenewableLockRegistry 介面現在提供了新的 renewLock(Object lockKey, Duration ttl) 方法,允許您使用自定義生存時間值續訂鎖。JdbcLockRegistryRedisLockRegistry 都使用型別引數 DistributedLock 實現了 LockRegistryRenewableLockRegistry 介面。

以下是如何從登錄檔中獲取 DistributedLock 並以特定生存時間值獲取它的示例

DistributedLock lock = registry.obtain("foo");
Duration timeToLive = Duration.ofMillis(500);

if(lock.tryLock(100, TimeUnit.MILLISECONDS, timeToLive)){
    try {
        // do something
    } catch (Exception e) {
        // handle exception
    } finally{
        lock. unlock();
    }
}
© . This site is unofficial and not affiliated with VMware.