分散式鎖定
在許多情況下,針對某些上下文(甚至單一訊息)的操作必須以獨佔方式執行。一個例子是聚合器元件,我們必須檢查當前訊息的訊息群組狀態,以確定是否可以釋放群組或僅添加該訊息以供將來考慮。為此,Java 提供了一個 API,其中包含 java.util.concurrent.locks.Lock
實作。但是,當應用程式分散式和/或在叢集中執行時,問題會變得更加複雜。在這種情況下,鎖定具有挑戰性,並且需要一些共享狀態及其特定方法才能實現獨佔性要求。
Spring Integration 提供了一個 LockRegistrty
抽象,以及一個基於 ReentrantLock
API 的記憶體內 DefaultLockRegistry
實作。LockRegistrty
的 obtain(Object)
方法需要特定上下文的 lock key
。例如,聚合器使用 correlationKey
來鎖定圍繞其群組的操作。這樣,不同的鎖定可以同時使用。此 obtain(Object)
方法返回一個 java.util.concurrent.locks.Lock
實例(取決於 LockRegistry
實作),因此其餘邏輯與標準 Java 並行演算法相同。
從 6.2 版開始,LockRegistry
提供了一個 executeLocked()
API(此介面中的 default
方法),用於在鎖定時執行某些任務。此 API 的行為類似於眾所周知的 JdbcTemplate
、JmsTemplate
或 RestTemplate
。以下範例示範了此 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
。