メインコンテンツまでスキップ

分散ロック

共有リソースへのアクセスをリアルタイムで管理し、望ましい順序でデータをトランザクションできるようにします

場合によっては、アプリケーションインスタンス間で共有されるリソースがあり、順番にアクセスする必要があります。たとえば値をインクリメントする際に、2つのクライアントが同時に値 1 を読み取ると、それぞれが値を 2 にインクリメントしてしまいます。しかし望ましい動作は、値が2回インクリメントされて結果が 3 になることです。

このシナリオはレースコンディションの一例です。レースコンディションとは、システムが同時に2つ以上の操作を実行しようとする際に発生する状況です。しかしシステムの性質上、操作は適切な順序で行われなければなりません。

Squid は、共有データを適切に同期し、レースコンディションを解決するために開発者が利用できる分散ロックを提供します。

分散ロックの作成

共有リソースへのアクセスを同期するには acquireLock メソッドを使用し、このロックを一意に識別する文字列値を mutex パラメータに渡します:

Client code
const distLock = await squid.acquireLock('YOUR_MUTEX_STRING');

このメソッドは、指定された mutex の分散ロックに解決される promise を返します。別のクライアントがロックを確保していて利用できない場合、その promise はロックが解放されるまで、またはサーバーとの接続が失われるまで解決を待機します。

ロックの解放

ロックは release() メソッドが呼び出されたとき、またはサーバーへの接続が失われたときに解放されます。クライアントが切断された場合、ロックは自動的に解放されます。

Client code
// 作業が完了したらロックを解放する
distLock.release();

これらのメソッドを組み合わせると、ワークフローは次のようになります:

Client code
const distLock = await squid.acquireLock('YOUR_MUTEX_STRING', 5000);

try {
// 共有リソースに対してアクションを実行
} catch (e) {
// timeout のようなエラーを捕捉
} finally {
distLock.release(); // 不要になったらロックを解放
}

ロックが解放されたかどうかを確認するには isReleased() メソッドを使用します。このメソッドは boolean を返し、ロックが解放されていれば true になります。

Client code
console.log(distLock.isReleased()); // true or false

ロック解放時にアクションを実行するには observeRelease() メソッドを使用できます。これは、ロックが解放されたときに emit する observable を返します。

Client code
distLock.observeRelease().subscribe(() => {
// ロック解放時に何かを実行
});

コールバックで分散ロックを管理する

withLock() メソッドを使って分散ロックを管理することもできます。このメソッドは、指定された mutex のロックを保持した状態で与えられたコールバックを実行します。コールバックが終了するとロックが解放されるため、withLock() を使用する場合は release() メソッドは不要です。

Client code
squid.withLock('YOUR_MUTEX_STRING', async () => {
// データの読み取りや更新などのタスクを完了
return; // 関数を返すこともできます
});

分散ロックの保護

デフォルトでは、分散ロックは完全に保護されており、Squid backend の security function が許可した場合にのみ呼び出すことができます。詳細は、backend ドキュメントの分散ロックの保護を参照してください。