JDBC ロックレジストリ
バージョン 4.3 は JdbcLockRegistry を導入しました。特定のコンポーネント(アグリゲーターやリシーケンサーなど)は、LockRegistry インスタンスから取得したロックを使用して、一度に 1 つのスレッドのみがグループを操作するようにします。DefaultLockRegistry は、単一のコンポーネント内でこの機能を実行します。これらのコンポーネントで外部ロックレジストリを構成できるようになりました。共有 MessageGroupStore で使用する場合、JdbcLockRegistry を使用して複数のアプリケーションインスタンスにこの機能を提供し、一度に 1 つのインスタンスのみがグループを操作できます。
ローカルスレッドによってロックが解除されると、通常、別のローカルスレッドがすぐにロックを取得できます。別のレジストリインスタンスを使用するスレッドによってロックが解放された場合、ロックを取得するのに最大 100 ミリ秒かかることがあります。
JdbcLockRegistry は LockRepository 抽象化に基づいており、DefaultLockRepository 実装があります。データベーススキーマスクリプトは org.springframework.integration.jdbc パッケージにあり、特定の RDBMS ベンダー用に分割されています。例: 次のリストは、ロックテーブルの H2 DDL を示しています。
CREATE TABLE INT_LOCK (
LOCK_KEY CHAR(36) NOT NULL,
REGION VARCHAR(100) NOT NULL,
CLIENT_ID CHAR(36),
CREATED_DATE TIMESTAMP NOT NULL,
EXPIRED_AFTER TIMESTAMP NOT NULL,
constraint INT_LOCK_PK primary key (LOCK_KEY, REGION)
);INT_ は、ターゲットデータベースの設計要件に応じて変更できます。DefaultLockRepository Bean 定義で prefix プロパティを使用する必要があります。
場合によっては、1 つのアプリケーションが、分散ロックを解放してデータベース内の特定のレコードを削除できない状態に移行することがあります。この目的のために、そのようなデッドロックは、次回のロック呼び出し時に他のアプリケーションによって期限切れになります。DefaultLockRepository の timeToLive (TTL) オプションは、この目的のために提供されています。特定の DefaultLockRepository インスタンスに保存されるロックに CLIENT_ID を指定することもできます。その場合は、コンストラクターパラメーターとして DefaultLockRepository に関連付けられる id を指定できます。
バージョン 5.1.8 から、JdbcLockRegistry は idleBetweenTries (ロックレコードの挿入 / 更新の実行間でスリープする Duration ) で構成できます。デフォルトでは、100 ミリ秒であり、一部の環境では、非リーダーがデータソースとの接続を頻繁に汚染します。
バージョン 5.4 以降、RenewableLockRegistry インターフェースが導入され、JdbcLockRegistry に追加されました。ロックされたプロセスがロックの有効期間よりも長くなる場合、renewLock() メソッドはロックされたプロセス中に呼び出される必要があります。これにより、有効期間が大幅に短縮され、デプロイは失われたロックを迅速に再取得できます。
| ロックの更新は、ロックが現在のスレッドによって保持されている場合にのみ実行できます。 |
バージョン 5.5.6 以降、JdbcLockRegistry は JdbcLockRegistry.setCacheCapacity() を介して JdbcLockRegistry.locks 内の JdbcLock のキャッシュを自動的にクリーンアップする機能をサポートしています。詳細については、Javadoc を参照してください。
バージョン 6.0 以降では、アプリケーションコンテキストからのプライマリ Bean に依存する代わりに、DefaultLockRepository に PlatformTransactionManager を提供できるようになりました。
バージョン 6.1 以降、DefaultLockRepository をカスタム insert、update、renew クエリ用に設定できるようになりました。この目的のために、対応する setter と getter が公開されています。例: PostgreSQL ヒントの挿入クエリは次のように設定できます。
lockRepository.setInsertQuery(lockRepository.getInsertQuery() + " ON CONFLICT DO NOTHING"); バージョン 6.4 以降、LockRepository.delete() メソッドは分散ロックの所有権を削除した結果を返します。また、JdbcLockRegistry.JdbcLock.unlock() メソッドは、ロックの所有権が期限切れの場合に ConcurrentModificationException をスローします。
バージョン 7.0 以降、JdbcLock は DistributedLock インターフェースを実装し、ロックステータスデータの TTL(Time to Live)カスタマイズ機能をサポートします。lock(Duration ttl) または tryLock(long time, TimeUnit unit, Duration ttl) メソッドを使用して、指定した TTL 値で JdbcLock を取得できるようになりました。JdbcLockRegistry では、新しい renewLock(Object lockKey, Duration ttl) メソッドが提供され、カスタム TTL 値でロックを更新できるようになりました。同じ JdbcLockRegistry に格納されているすべての JdbcLock インスタンスのデフォルトの TTL を、新しいコンストラクター JdbcLockRegistry(LockRepository client, Duration expireAfter) で設定できるようになりました。LockRepository と DefaultLockRepository の API もこの機能をサポートするように変更されました。
すでに ロックテーブルに新しい列を追加するための Postgres DDL の例を次に示します。 |