Skip to content

リース、Heartbeat、復旧

この記事は英語版から翻訳されました。最新版は英語版をご覧ください。

ワークフロー/ジョブシステムは、誰が現在その作業を実行してよいかをリースで決めます。リースは時間制限付きのclaimであり、他のワーカーが完全に止まった証明ではありません。heartbeatは進行中であることを示しリースを延長します。リース期限切れで復旧が始まりますが、期限切れワーカーがまだ動く可能性があるため、冪等性とfencingが必要です。

Lease vs Lock

仕組み意味
Lockreleaseまで排他。owner死亡時に危険
Leasedeadlineまで排他
Heartbeatownerが生存/進捗を示しlease延長
Fencing tokenstale ownerをdownstreamが拒否する単調増加token

leaseは無期限lockより復旧しやすいですが、exactly-once executionを保証しません。

基本フロー

後からtoken 43のワーカーが来たら、downstreamはtoken 42のstale writeを拒否します。

Lease Duration

短すぎる長すぎる
正常なGC pause/遅いcallで重複attemptworker death後の復旧が遅い
downstream duplicate圧力増加stuck jobが長く見えない
heartbeat traffic増加false expiration減少

平均runtimeではなく、P99 heartbeat delayと余裕で決めます。

Heartbeat Payload

json
{
  "processed_records": 250000,
  "last_object_key": "logs/2026/06/15/part-00042.gz",
  "updated_at": "2026-06-15T10:30:00Z"
}

checkpoint境界を設計していれば、retry時にゼロからやり直さず再開できます。

Recovery Controller

復旧はワーカーの副作用ではなくcontrollerにします。stuck-state policyを明示的にテストできます。

Orphan Detection

orphanとは、terminalでもrunnableでもない作業です。

  • leaseなしでstatusがrunning
  • 永続化されていないtimerを待っている
  • Activity完了したがcompletion eventがない
  • parent cancel後もchild jobが動く

reconciliation jobで不可能状態をscanし、修復またはalertします。

Fencing

sql
UPDATE resources
SET value = :new_value,
    fencing_token = :token
WHERE id = :id
  AND fencing_token < :token;

更新行数が0ならworkerはstaleです。

障害モード

障害原因対策
split executionlease切れ後も旧workerが継続fencingと冪等副作用
lost heartbeatnetwork bliplease marginとheartbeat retry
zombie workerprocessは固まるがheartbeatだけ続くlivenessでなくprogress heartbeat
stuck runningworkerがrelease前に死亡expired-lease scanner
double completion2 workersがcompletion競合CAS terminal transition

関連パターン

MITライセンスの下で公開。Babushkaiコミュニティが構築。