クライアントがキーを取得(A)すると、サーバーは次の3つのうちいずれかで応答します。
| キー状態 | サーバー動作 | 応答 |
|---|---|---|
| 未登録 | 即座に登録(失効 = now + lease)、トークン発行 | A + token + key |
| 登録済み + 失効済み | 更新(now + lease)、新しいトークンを発行 | A + token + key |
| 登録済み + 有効(占有中) | 待機列に登録、応答を保留 | 返却/失効時にA、wait超過時にT |
R)すると、待機列の先頭に直接引き渡されます — 再競合なしに新しいトークンとともに即座に渡ります。leaseは安全網です。 クライアントが停止したり返却を忘れたりしても、leaseの時間が経過すればサーバーが自動的に キーを回収して次の待機者に渡すことができます。そのため、通常の返却フローとは別に、常にleaseを 余裕を持たせつつ、停止時にも長く縛られすぎない値に設定するのがよいでしょう。waitは取得待機の上限です。 0なら無限待機、それ以外はその時間(秒)内に受け取れなければサーバーが 諦めてT(タイムアウト)で応答します — 付与なしで終わるため、ロックが漏れることはありません。A応答に含まれるtokenはそのgrantの単調増加するu64です。取得のたびに以前のどのトークンよりも大きい 値が発行されます。フェイルオーバーが発生しても、新しくアクティブになったノードはレプリケーションで受け取った最大トークンより大きい 値から続けます(承継) — そのため、クラスター全体を通してもトークンは増加し続けます。
保護対象のリソース(口座、ファイル、注文など)が「今持っているトークンが最後に見たトークンより大きいか」だけを検証すれば、 lease失効後に遅れて動き出したクライアントが、すでに無効化された低いトークンでアクセスしようとするのを拒否できます。 これにより、ロックサーバーが常に完全に一貫していなくても安全性を保つことができます。
公式クライアントは共通して次のように動作します(言語ごとの詳細なAPIはライブラリを参照)。
leaseが回収しますが、その前に他の待機者へより早く渡すためです)。peersリストの順序が昇格の優先順位です(先頭が最優先)。生存しているノードのうち優先順位が最も高い 1台がアクティブ、残りはその状態をリアルタイムでレプリケーションを受け取るスタンバイになります。M)され、 そちらへ移動します。Ctrl+C)時には、アクティブが後継に先に昇格を渡し(ハンドオフ)た後にクライアントを リダイレクトすることで、アクティブ不在の期間を最小化します。この昇格方式はクォーラム(過半数投票)ベースではありません。 そのため奇数/偶数台数は重要ではなく、1台でも 生存していればサービスが維持されます。
| サーバー台数 | 無停止 | 同時障害許容 | 備考 |
|---|---|---|---|
| 1台 | ✗ | — | 最も高速。再起動時に短い瞬断が発生 |
| 2台 | ✓ | 1台 | 無停止の最小構成。 ほとんどの場合これで十分 |
| 3台 | ✓ | 2台 | 1台点検中でも冗長性を維持 |
| 4台以上 | ✓ | N−1台 | 伝播コストが増えるだけ — 推奨しない |
優先順位ベースの昇格は合意ではないため、ネットワークパーティションの瞬間には両方が一時的に同時にアクティブになる 可能性があり、非同期レプリケーションの特性上フェイルオーバーの瞬間に一部のgrantが失われる可能性があります。つまりフェイルオーバー/パーティション区間では 相互排他が100%保証されるわけではありません。 強い保証が必要な場合は、先に説明したフェンシングトークンを保護対象の リソースが検証するように実装してください — 古い(小さい)トークンを拒否すれば、ロックサーバーが完全に一貫していなくても 安全です。