リーダーの選択
1)リーダーが必要な理由と彼がまったく正当化されたとき
リーダー-クリティカルアクションを実行する排他的な権利を持つノード:クラウン/ETLの開始、シャードの調整、キーの配布、構成の変更。不変量(「one performer」)を単純化するが、リスク(SPOF、再選、遅延)を追加する。
リーダーシップを使用する場合:- 実行の一意性を必要とします(例えば、請求アグリゲータは1分に1回)。
- 変更をシリアル化する必要があります(構成レジスタ、分散ロック)
- クラスタプロトコルはリーダーシップ・レプリケーション(Raft)を想定しています。
- 問題はidempotenceおよびキーによる順序によって解決されます;
- 作業盗難/キューを介して並列化することができます。
- 「リーダー」が唯一の狭いポイント(ワイドファンイン)になります。
2)ベースモデル: lease+quorum+epoch
プライバシーポリシー
リース:リーダーはT秒の権利があります。更新する必要があります。
ハートビート:周期的な延長/生きている信号。
Epoch/term:単調に成長するリーダーシップ数。「古い」リーダーを認識するのに役立ちます。
フェンシングトークン:リソース消費者(データベース/ストレージ)が古いリーダーの操作をチェックして拒否するのと同じモノトーン番号。
不変量
いつでも、複数の実際のリーダー(安全)。
失敗した場合、進歩は可能です:新しいもの(生きていること)は合理的な時期に選出されます。
リーダーの操作は時代を伴っています。シンキーは新しい時代を受け入れるだけだ。
3)アルゴリズムとプロトコルの概要
3.1いかだ(リーダーシップ・レプリケーション)
ステータス:フォロワー→候補→リーダー。
タイマー:ランダムな選挙タイムアウト(ジッタ)、RequestVote;リーダーは、ハートビートとしてAppendEntriesを保持します。
保証:quorum、標準的な前提条件の下の分割頭脳無し、論理単調(term/index)のlogbook。
3.2パクソ/シングルデクレ/マルチパクソ
コンセンサスの理論的基礎;実際には-バリエーション(例えば、Multi-Paxos)と「選択されたコーディネーター」(リーダーアナログ)。
直接実装するのが難しい。既製の実装/ライブラリはより頻繁に使用されます。
3.3 ZAB (ZooKeeper原子放送)
ZKメカニズム:回復フェーズを備えたリーダーシップジャーナルのレプリケーション;リーダーシップのようなプリミティブのためのepochs (zxid)とsequential ephemeralノード。
3.4いじめ/チャンロバーツ(リング/モナーク)
クォーラムなしの静的トポロジーのための「トレーニング」アルゴリズム。部分的なネットワーク障害/パーティションを考慮しないでください-販売には適用されません。
4)実用的なプラットフォーム
4.1 ZooKeeper
EPHEMERAL_SEQUENTIALパターン:プロセスは'/leader/lock-XXXX'を作成します。最小値はリーダーです。
セッションが失われてしまった→ノードが消えてしまう→再選択が瞬時に行われます。
「前任者」を待つことによって正義。
4.2 etcd(いかだ)
クラスタレベルでのネイティブリーダーシップ;アプリケーションの場合-etcd concurrency: 'Session+Mutex/Election'。
リースID TTL、 keepalive;キー値にエポックを格納できます。
4.3領事
'session'+'KV ackire':キーを保持している人がリーダーです。セッション中のTTL/ハートビート。
4.4 Kubernetes
コーディネーションAPI('コーディネート。k8s。io/v1'):'リース'c' ホルダーID'、'リース期間秒'、'更新時間'。
クライアントライブラリ'leaderelection' (client-go)は、キャプチャ/更新を実装します。リーダーポッドに最適です。
5)「安全な」リーダーを構築する方法
5.1時代を保ち、囲うこと
各鉛はepochを増加します(例えば。etcd/ZKリビジョンzxidまたは個別カウンタ)。
リーダーのすべての副作用(データベースへの書き込み、タスクの実行)は'epoch'を送信し、比較する必要があります:sql
UPDATE cron_state
SET last_run = now(), last_epoch =:epoch
WHERE name = 'daily-rollup' AND:epoch > last_epoch;
古いリーダー(分割脳の後)は拒否されます。
5.2タイミング
'leaseDuration' ≥ '2-3 × heartbeatInterval+network+p99 GC pause'。
選挙タイムアウト-候補者が衝突しないようにランダム化(ジッター)。
更新が失われた場合は、直ちに重要な操作を停止します。
5.3アイデンティティ
'holderId=node#pid#startTime#rand'。更新/削除時には、同じホルダーを確認してください。
5.4ウォッチャー
すべてのフォロワーは「、リース/選挙」の変更を購読し、ステータスに応じて開始/停止します。
6)実装: フラグメント
6.1 Kubernetes (Go)
go import "k8s. io/client-go/tools/leaderelection"
lec:= leaderelection. LeaderElectionConfig{
Lock: &rl. LeaseLock{
LeaseMeta: metav1. ObjectMeta{Name: "jobs-leader", Namespace: "prod"},
Client: coordClient,
LockConfig: rl. ResourceLockConfig{Identity: podName},
},
LeaseDuration: 15 time. Second,
RenewDeadline: 10 time. Second,
RetryPeriod: 2 time. Second,
Callbacks: leaderelection. LeaderCallbacks{
OnStartedLeading: func(ctx context. Context) { runLeader(ctx) },
OnStoppedLeading: func() { stopLeader() },
},
}
leaderelection. RunOrDie(context. Background(), lec)
6.2 etcd(行く)
go cli, _:= clientv3. New(...)
sess, _:= concurrency. NewSession(cli, concurrency. WithTTL(10))
e:= concurrency. NewElection(sess, "/election/rollup")
_ = e. Campaign (ctx, podID )//blocking call epoch: = sess. Lease ()//use as part of fencing defer e. Resign(ctx)
6.3 ZooKeeper(ジャワ、キュレーター)
java
LeaderSelector selector = new LeaderSelector(client, "/leaders/rollup", listener);
selector. autoRequeue();
selector. start(); // listener. enterLeadership () performs leader work with try/finally
7)再選とサービスの劣化
チャートのリーダー→「魚の骨」の鋭いフラッピング。leaseDurationRenewDeadlineを増やし、GC/CPUのこぎりを排除することで処理します。
再選択期間については、ブラウンアウトを有効にします。バックグラウンドタスクの強度を下げるか、確認されたリーダーシップに完全にフリーズします。
長いジョブの場合は、リーダーの変更後にチェックポイント+idempotent dokatを実行します。
8)スプリットブレイン: 外出を控える方法
クォーラムでCPストア(etcd/ZK/Consul)を使用する。クォーラムなしではリーダーを取ることはできません。
クォーラムアービターなしでAPキャッシュでリーダーシップを構築しないでください。
CPモデルでも、リソースレベルでフェンシングを続けます-これはまれな異常なシナリオ(一時停止、運転手の立ち往生)に対する保険です。
9) Observabilityおよび操作
メトリクス
'leadership_is_leader {app}'(ゲージ0/1)
'election_total {result='resign}'
'lease_renew_latency_ms {p50、 p95、 p99}'、 'lease_renew_fail_total'。
'epoch_value'(クラスタモノトニー)
'flaps_total'はウィンドウごとの引出線シフト数です。
ZK/etcdの場合:レプリケーションラグ、クォーラムヘルス。
アラート
頻繁な鉛の変更(1時間の>N)。
更新失敗'更新'/高いp99。
epoch infeasibility(異なるノードで2つの異なるエポック)。
(ビジネスが許可していない場合)X秒よりもリーダーはありません。
ログ/トレイル
リンクイベント:'epoch'、 'holderId'、 'reason' (lost lease、 session expired)、 'duration_ms'。
10)テストプレイブック(ゲーム日)
パーティション:2つのゾーン間のネットワークを破る-リーダーシップはクォーラム部分でのみ許可されます。
GCストップ:人為的に5-10sのリーダーを停止-リースを失い、動作を停止する必要があります。
クロックスキュー/ドリフト:正確さがウォールクロックに依存しないことを確認します(フェンシング/エポックが保存されます)。
Kill -9:突然のリーダーのクラッシュ→新しいリーダー≤ leaseDuration。
遅いストレージ:ディスク/ラフトログを遅くする-選挙時間、デバッグタイミングを推定します。
11)アンチパターン
Redisによる「リーダー」「SET NX PX」はフェンシングなし、クォーラムなし。
'leaseDuration'は重要な動作期間のp99未満です。
リーダーシップを失った後の作業の停止/継続(「私は分を終了します」)。
選挙タイマー→選挙嵐のジッタの欠如。
チェックポイントのない単一のロングジョブ-各フラップは、ゼロからのリプレイをもたらします。
リーダーシップとトラフィックルーティングの密接なリンク(スティッキー)フォールバックなし-フラップのボトムスは5xxを取得します。
12)実装チェックリスト
- クォーラムアービターを選択した場合はetcd/ZK/Consul/K8sリースとなります。
- すべてのリーダーの副作用にepoch/fencingを貯え、渡して下さい。
- 設定されたタイミングは、ネットワーク/GCマージンを持つ'leaseDuration'、 'renewDeadline'、 'retryPeriod'です。
- ウォッチャーを内蔵し、リーダーシップが失われたときに正しいシャットダウンを行います。
- リーダーシップタスクはidempotentとcheckpointです。
- メトリック/アラートとログ'epoch/holderId'が有効になります。
- 開催されたゲーム日:パーティション、GCストップ、キル、クロックスキュー。
- 政治家は文書化されている:誰が/リーダーが何をするか、誰が彼を置き換えることができるか、どのように画期的な対立を解決するか。
[The] Degradation Plan: leaderlessシステムが行うこと。
- 性能テスト:負荷の下のフラップはSLOを破壊しません。
13) FAQ
Q:クォーラムなしでリーダーシップを構築できますか?
A: prodでは、いいえ。CPコンポーネント(quorum)または同等の保証を持つクラウドサービスが必要です。
Q:リースがあればなぜepochか?
A:リースは生存性を提供しますが、分離/一時停止後の「古いリーダー」から保護しません。エポック/フェンシングは、古いリーダーの効果を無効にします。
Q: K8sのタイミングのデフォルトは何ですか?
A:多くの場合、' '、 ' '、 ' ' 使用されます。p99の負荷とGCにマッチします。
Q:リーダーシップを現地でどのようにテストしていますか?
A: 3-5インスタンスを実行し、ネットワーク(tc/netem)をエミュレートし、一時停止(SIGSTOP)、キルリーダー(SIGKILL)を実行し、メトリック/ログ/エポックをチェックします。
Q:リーダーを変更する際の長いタスクはどうすればよいですか?
A:チェックポイント+idempotent docat;リーダーシップの喪失の場合-資源の即時停止と解放。
14)合計
リーダーの信頼できる選択は、クォーラムアービター+時代の規律です。リーダーシップをハートビートでリースとして維持し、フェンシングトークンですべての効果を打ち負かし、余裕を持ってタイミングを設定し、リーダーのタスクを偶然で観察可能にし、定期的にクラッシュを失います。その後「、1人だけ」のパフォーマーはスローガンではなく、一時停止、ネットワークの気まぐれ、人間のエラーに耐性がある保証です。