分散式鎖定

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

Spring Integration 提供了一個 LockRegistrty 抽象,以及一個基於 ReentrantLock API 的記憶體內 DefaultLockRegistry 實作。LockRegistrtyobtain(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 為分散式鎖定提供以下 LockRegistrty 實作

Spring Integration AWS 擴充功能也實作了 DynamoDbLockRegistry