共有排他ロックは取得側だけでなく処理側も所有権を再確認する
並行処理
設計判断
非同期処理
信頼性
判断
運用
共通の排他ロックで複数種類の worker やジョブを直列化する設計では、ジョブ作成時の lock 取得だけでは不十分。stale lock の奪取、キューメッセージの再配信、worker の異常終了があると、古い message が後から処理を再開し、新しい所有者と並行実行する可能性がある。
判断基準
- 共有 lock を排他の正本にするなら、すべての処理主体が同じ lock を見る。片方の worker だけ task status を見る、別の worker だけ lock を見る、という非対称な正本を作らない。
- worker は処理開始時に、lock が自分の job ID / owner ID を指していることを条件付き更新や heartbeat 更新の結果で確認する。
- 長時間処理では、処理中も heartbeat を更新し、chunk 境界など副作用のまとまりごとに所有権を再確認する。所有権を失っていたら後続処理を止める。
- stale lock を別ジョブが奪取できる設計では、古い message の再配信を正常系として扱う。再配信側が lock 所有権を持っていなければ、処理本体へ進ませない。
落とし穴
ジョブ作成時の排他チェックだけを見て「同時実行しない」と判断すると、再配信や stale 復旧の経路で不変条件が破れる。とくに複数種類の worker が同じ資源を扱う場合、片方だけに所有権チェックや heartbeat を実装すると、古い経路が新しい lock 所有者を無視して動けてしまう。
検証
古い worker の message を再配信させる前に、同じ資源の lock を別 job に奪取させる。再配信された worker が処理本体に入らず、所有権喪失として停止することを確認する。処理中に lock 所有者を差し替えた場合も、次の chunk 境界で停止することを確認する。