bash/pythonのための優雅な原子分散ロックか。

bash/pythonのための優雅な原子分散ロックか。

単一ノードの複数のプロセスがいくつかのコードを同時に実行しないようにするために、いくつかのアトミックコマンド(たとえば、またはlnmkdirに基づいてアドバイザリロックを実装しますflock

複数のプロセスが特定のコードを非同時実行するかどうかを確認する方法多くの種類ノード(つまり、ネットワーク上で実行されているインスタンスは1つしか許可されていません)? Linuxでは、bashスクリプトまたはpythonスクリプトでこれを実行したいと思います。

NFSロックやRedisが利用可能であることを知っていますが、この複雑さのオーバーヘッドを経験したくありません。公開鍵ベースのSSHを使用できます。私はロックマネージャとして機能する追加のマシンのオーバーヘッドを望んでいません。理想的には、管理者はノードの1つをロックマネージャとして指定する必要はありません。定足数について心配する必要はありません。ノードに接続できなくなったら、続行する必要はありません。

理想的には、次のようにすべてのノードで1つのコマンドを呼び出すことができます。

distlock --lock --nodes=nodeA,nodeB,nodeC --resource=resourceX || error "can't lock"
...
distlock --unlock --nodes=nodeA,nodeB,nodeC --resource=resourceX

これまで(考えとインターネット検索を通じて)私が思いついた最善の方法は、各ノードに対して次のプロセスに従うことです。

  1. 構成ファイルからノードのリストを読み取ります。 (ファイルは手動で作成され、すべてのノードにコピーされます。)
  2. ロックマネージャノードがノードリストのアルファベット順に最初のノードであることを確認してください。
  3. 現在実行中のスクリプトインスタンスの場合はい決定されたロックマネージャノードで通常の方法でローカルロックファイルを作成します(ロックファイルにはpidが含まれています)。
  4. 現在実行中のスクリプトインスタンスいいえ識別されたロックマネージャノードで、次の操作を行います。
    1. ssh特定のロックマネージャノードへのフォーク(例:coprocbashを使用)
    2. ロックファイルを作成して...
    3. 標準入力(メインスクリプトで検出)からテキストを1行読み(メインスクリプトがまだ送信していないためまだ受信していない)、pidファイルが古くならないようにします。決定したロック管理ノードの様子)
  5. 私が保護したいコードを実行してみてください
  6. ロックを解除します(ロックがローカルの場合は、ロックファイルを削除するか、上記のテキスト行を分岐SSHに送信して終了するのを待ちます)。

これは私の要件を満たしています。複数のノードが上記のコードを並列に実行すると、正確に1つのノードが正常にロックされ、ネットワーク接続が失敗した場合、他のノードはロックされません。これにより、1つのノード(カスタマイズされたロックマネージャ)が機能し続けることができます。他のノードはそれを行うことはできません(つまり、クラスターはセミブレイン状態になりますが、スプリットブレイン状態ではありません)。

しかし、私はシンプルでスクリプト化しやすいツールを使用して、よりエレガントな代替ソリューションのアイデアを他の人に要求したいと思います。

関連情報