コアデータ協調制御

分散ロック

自動で期限切れになり、所有者が安全に解放できるロックで、ジョブを一度に1つのワーカーだけが実行するようにします。

取得に必要なコマンド
1
安全な解放に必要なコマンド
1
Luaスクリプト
0
ステップ 1 / 5
ワーカーAがロックを取得

NXは誰も保持していない場合にだけ取得します。PX 30000により、Aが停止すると30秒で期限切れになります。

サンプルセッションplaying
# ワーカーAがロックを取得
hotkv> SET lock:billing-run tok-a81f NX PX 30000
OK

実際のHotKVコマンドと応答例を使ったアニメーションのウォークスルーです。任意のステップをクリックすると、そこに移動します。 コマンドと応答は、HotKVで実際に入力し表示されるとおり英語のままです。

課題

複数のマシンで動くcronジョブ、決済の確定、キャッシュの再構築は、同時に二重に実行されてはなりません。有効期限のないロックは、所有者がクラッシュすると永遠に保持されたままになります。また単純なDELでロックを解放すると、自分のロックが期限切れになった後に他人のロックを削除してしまうおそれがあります。

HotKVでの解決方法

NXとPXを付けたSETは、誰も保持していない場合にだけロックを取得し、有効期限を付けるため、クラッシュした所有者が永遠に保持し続けることはありません。各所有者はランダムなトークンを値として保存します。IFEQを付けたDELEXは、ロックがまだ自分のトークンを保持している場合にだけ削除します。これは以前ならLuaスクリプトが必要だった安全な解放です。

ステップごとに

コマンドごとに何が起きるか

  1. 01

    ワーカーAがロックを取得

    NXは誰も保持していない場合にだけ取得します。PX 30000により、Aが停止すると30秒で期限切れになります。

    SET lock:billing-run tok-a81f NX PX 30000
  2. 02

    ワーカーBは退けられる

    ロックは保持されているため、Bはnilを受け取り、今回の実行をスキップします。

    SET lock:billing-run tok-b22c NX PX 30000
  3. 03

    Aが作業を行う

    請求ジョブを実行するのは1つのワーカーだけです。

    PTTL lock:billing-run
  4. 04

    自分のロックだけを解放

    DELEXは、値がまだAのトークンである場合にだけキーを削除します。

    DELEX lock:billing-run IFEQ tok-a81f
  5. 05

    誤ったトークンでは何も起きない

    Aが遅すぎて、Bがロックを保持していた場合でも、Aの解放はBのロックに手を触れません。

    DELEX lock:billing-run IFEQ tok-stale
活用シーン

実際のシナリオ

スケジュールジョブ

同じcronがすべてのインスタンスで動き、ロックによってそのうちの1つだけが作業を行います。

決済

1つの注文に対する確定と返金の操作は直列化されるため、重なることはありません。

キャッシュスタンピードの防止

高コストなキャッシュエントリーを再構築するのは1つのリクエストだけで、他は待つか古い値を返します。

標準搭載

得られるもの

有効期限付きで取得

SET NX PXは、空いている場合にだけタイムアウト付きでロックを取得します。

SETNXPX

安全な解放

DELEX IFEQは、値が自分のトークンと一致する場合にだけ削除します。

DELEX

作業中に延長

残り時間を確認し、長いジョブでは延長します。

PTTLPEXPIRE

ダイジェストで比較

大きな値では、DELEX IFDEQが値全体の代わりにダイジェストを比較します。

DIGESTIFDEQ
リファレンス:SETDELEXDIGEST

よくある質問

単にロックをDELすればよいのでは?

自分のロックが期限切れになって別のワーカーが取得していた場合、単純なDELはそのワーカーのロックを削除してしまいます。DELEX IFEQは、ロックがまだ自分のトークンを保持している間だけ削除します。

有効期限はどのくらいにすべきですか?

ジョブに通常かかる時間より長くします。長いジョブでは、ロックを保持している間に定期的に有効期限を延長してください。

安全な解放にLuaは必要ですか?

いいえ。DELEXが比較と削除を1つのコマンドで行います。

関連するユースケース

ご自身のワークロードで試してみましょう

HotKVはRedisプロトコルに対応しているため、既存のクライアントを向けるだけで、これらと同じコマンドを実行できます。