2020年12月6日日曜日

複数ホスト間の排他制御

ウェブサービスを開発していると、集計とか課金とかでバッチ処理を行いたい場合が出てきます。

バッチ処理は冗長化のために複数のホストマシンに起動設定しているけど、実行はどれか1つだけで行いたいという場合もあると思いますが、その方法をいろいろ調べてみました。

まあ今さらかよって話ですが。

MySQLのアドバイザリーロック

MySQLにはGET_LOCK() / RELEASE_LOCK()というアドバイザリーロックの仕組みがあります。

これは「GET_LOCK()でロックを取得できたら、RELEASE_LOCK()で解放するかDBコネクションが切れるまで他のコネクションはロックを取得できない」というものです。

これなら不意にプロセスが落ちた場合でもロックが開放されるし完璧じゃね?と思ったのですが、このアドバイザリーロックは2つのアドバイザリーロックを同時に取得できない(2番目のロックを取得したら最初のロックが外れる)という欠点があります。

つまり排他制御が必要なバッチを複数起動できないということです。これはアカン。

結局KVSがいいのかも

結局シャレた方法を使わず、オーソドックスにKVSを使うことにしました。

例えばMemcachedを使う場合は

  • 取得したいロックの名前をキーにしてADDコマンドを呼び出す(値は何でもいい)
  • ADDが成功したらロック取得成功 / 失敗したらロック取得も失敗
  • DELETEコマンドでロックを解放

RedisのSETNXでも同じことができます。

これなら複数のロックも取得できますが、バッチプロセスがクラッシュしたときにロックが開放されないという問題があります。

これを回避するために、ADDコマンドでキーの有効期限を「バッチ処理が確実に終わっているであろう時間」にセットしておきましょう。

何も新規性のない情報でした。何か画期的な方法を期待していた方ごめんなさい。

0 件のコメント:

コメントを投稿