Performing cluster maintenance#
実稼働に移行する前にクラスター構成を確認し、継続的なメンテナンスを注意深く計画します。単一ロケーションのクラスターでの簡単な操作は、複数のロケーションがアクティブな場合、クロスロケーションフェールオーバーをトリガーし、レプリケーションラグを導入し、競合を発生させる可能性があります。
クラスター構成の検証#
セットアップが完了したら、運用に行く前に、サブグループ、ルーティング、およびコミットスコープが正しく構成されていることを確認します。
サブグループとそのルーティング設定を確認します。
SELECT node_group_name, node_group_enable_raft, node_group_enable_routing
FROM bdr.node_group;
現在の書き込みリーダーを確認します。
SELECT node_group_name, write_lead
FROM bdr.node_group_routing_summary;
コミットスコープ構成を確認します。
SELECT commit_scope_name, commit_scope_origin_node_group, commit_scope_rule
FROM bdr.commit_scopes;
データベースの変更の管理#
地理分散クラスターでは、スキーマの変更と日常的なメンテナンスの動作が異なります。
DDLはクラスター全体のロックを取得しますが、 VACUUM やANALYZE
のような操作は各ノードでローカルに実行されますが、レプリケーションスロットのラグの影響を受ける可能性があります。
DDLの実行#
DDL操作はクラスター全体のロックを取得しますが、ロックのタイプとタイミングは操作によって異なります。
ALTER TABLE やCREATE INDEX
などのスキーマ変更は、すべてのノードでグローバルDDLロックを同時に取得し、ロック取得時間は最も遠いノードへの往復時間とほぼ等しくなります。
DROP TABLE
などのオペレーションは、レプリケーションもフラッシュするグローバルDMLロックを取得し、完了時間はネットワーク遅延のみではなく現在のレプリケーションラグに依存します。
どちらの場合も、長時間実行DDLは、ロックが保持されている間レプリケーションをブロックし、失敗したDDLは場所間で一貫性のない状態を残す場合があります。
リスクを軽減するには、 DDLトランザクションを最小限に抑え、単一のトランザクションで複数のDDL変更を組み合わせないようにします。実際のクロスロケーションのレイテンシーをシミュレートするステージング環境でDDLタイミングをテストします。メンテナンス時間帯にDDLをスケジュールします。
VACUUMとANALYZEの実行#
VACUUM およびANALYZE
は、各ノードでローカルに実行され、レプリケートされません。
Autovacuumは各ノードで独立して動作するため、場所を超えて特別な調整は必要ありません。
PGD固有の懸念事項は、レプリケーションスロットの遅延です。オフラインまたは遅延ノードのスロットはcatalog_xmin
を抑制し、VACUUMがカタログテーブルをクリーニングできず、元のノードに肥大化が蓄積します。スロットラグを定期的にチェックして、これを早期にキャッチします。
SELECT target_name, state, replay_lag_bytes, replay_lag_size, xmin, catalog_xmin
FROM bdr.node_slots
ORDER BY replay_lag_bytes DESC;
書き込みリーダーシップの管理#
地理的分散クラスターでは、ノードの障害または計画的な操作が原因で、書き込みリーダーシップが場所間を移動する場合があります。レイテンシーに合わせてフェールオーバー検出を構成し、ノードをオフラインにする前にクォーラムを維持し、計画的なスイッチオーバーを使用して書き込みリーダーシップを安全に転送します。
フェイルオーバーの処理#
書き込みリーダーの障害が発生すると、PGDはTCPキープアライブと接続タイムアウトを介してそれを検出し、Raftコンセンサスを介して新しい書き込みリーダーを選択します。クロスロケーションのレイテンシーと許容可能なフェイルオーバー時間と一致するように次のパラメーターを調整します。
bdr.global_keepalives_idle、bdr.global_keepalives_interval、およびbdr.global_keepalives_countは、障害が発生した接続が検出される速さを制御します。bdr.global_connection_timeoutは、接続を確立するときに待機する最大時間を設定します。高遅延の展開では、この値を小さくして、完全なTCPタイムアウトを待たずに障害をより迅速に検出します。bdr.raft_global_election_timeoutは、新しい書き込みリーダーがトップレベルグループで選択されるまでの時間を制御します。bdr.raft_group_election_timeoutは、ロケーションごとのサブグループ選択に適用されます。予想されるクロスロケーション遅延がネットワークジッターからの誤選択を引き起こしている場合、これらの値を増やします。
クォーラムの維持#
ノードをオフラインにする前に、クラスターがクォーラム投票ノードのマジョリティを維持していることを確認します。クォーラムがないと、新しい書き込みリーダーは選択されず、クラスターは読み取り専用状態になり、手動介入が必要です。続行する前に、現在の投票ノードの数を確認してください。
SELECT nvoting_nodes, is_voting FROM bdr.stat_raft_state;
残りの投票ノードの数がマジョリティを下回る場合、ノードをフェンスまたは停止しないでください。 2つの場所の展開では、3番目の場所の監視ノードは、1つの場所に障害が発生した場合にクォーラムを維持するために必要な追加の投票を提供します。詳細は、 ノード分散の計画 を参照してください。
計画的なスイッチオーバーの実行#
計画的なスイッチオーバーの前に、ターゲットノードが正常であり、追い付いていることを確認します。現在のリーダーでアクティブな長時間実行トランザクションがないことを確認し、可能な場合はトラフィックの少ない時間帯にスイッチオーバーを実行します。
ターゲットノードのレプリケーションスロットがアクティブでストリーミングで、遅延がほぼゼロであることを確認します。
SELECT target_name, active, state, replay_lag_bytes, replay_lag_size
FROM bdr.node_slots
WHERE target_name = <target_node_name>;
スロットには、ゼロに近いactive = true 、state = 'streaming'
、およびreplay_lag_bytes が表示されるはずです。状態がcatchup
またはdisconnected
である場合、または遅延が高い場合、続行する前に待機します。
スイッチオーバーを開始します。
SELECT bdr.routing_leadership_transfer(
node_group_name := <group_name>,
leader_name := <target_node_name>
);
クラスターが正常な状態であることを確認します。
新しい書き込みリーダーが選択されたことを確認します。
SELECT node_group_name, write_lead
FROM bdr.node_group_routing_summary;
プロキシルーティングが新しいリーダーに更新されたことを確認します。
SELECT node_group_name, write_lead_name, previous_write_lead_name
FROM bdr.stat_routing_state;
新しいリーダーから他のノードへのレプリケーションが低い遅延でストリーミングされていることを確認します。
SELECT target_name, active, state, replay_lag_bytes, replay_lag_size
FROM bdr.node_slots
WHERE origin_name = <new_leader_node_name>;
すべてのスロットで、ゼロに近いstate = 'streaming'
およびreplay_lag_bytes が表示されるはずです。
ノードのメンテナンスの実行#
ローリング操作の場所を認識した順序に従い、ノードをオフラインにする前にフェンスします。
ロケーションをまたいだローリングオペレーション#
複数のノードに影響を与えるアップグレードまたはメンテナンスを実行する場合、次の順序に従って、クロスロケーションフェイルオーバーを最小限に抑え、できるだけ長く書き込みをローカルに保ちます。この順序は、各場所に独自の書き込みリーダーがあるローカルルーティングを想定しています。グローバルルーティングでは、クラスター全体に単一の書き込みリーダーがあるため、手順2をスキップして、最後にグローバル書き込みリーダーを処理します。
セカンダリロケーションの非リーダーノードから開始します。
セカンダリの場所の書き込みリーダーに移動しますこれにより、そのロケーション内でローカルフェイルオーバーが発生します。グローバルルーティングを使用する場合、手順2をスキップします。
プライマリロケーションの非リーダーノードに進みます。
プライマリ書き込みリーダーを最後に処理します。プライマリ書き込みリーダーのダウンは、クロスロケーションフェイルオーバーを発生させる可能性が最も高い操作です。
フェンシングノード#
フェンシングは、クラスターから削除せずにノードを書き込みリーダー資格から削除します。ノードの再起動が必要なメンテナンスの前、アップグレードの前、およびノードの状態に疑問がある場合に、フェンシングを使用します。
ノードをフェンスするには
SELECT bdr.alter_node_option(
node_name := <node_name>,
config_key := route_fence,
config_value := true
);
フェンスされたノードはクォーラムに参加し、レプリケーションの受信を継続するため、クラスターのコンセンサスを維持する能力に影響はありません。ただし、複数のノードを同時にフェンシングすると、可用性が低下する可能性があります。メンテナンス完了後は常にアンフェンス。
フェンスを解除するには
SELECT bdr.alter_node_option(
node_name := <node_name>,
config_key := route_fence,
config_value := false
);
クラスターの監視とインシデントへの対応#
操作の一部として、レプリケーションスロットの状態と競合率を定期的に確認します。以下のビューを使用して、インシデントが発生した場合の影響を評価し、復旧を確認します。
ネットワークパーティションの処理#
場所がパーティション化されると、クォーラムを保持する側が動作を継続します。クォーラムのない側は読み取り専用になります。分離された側のレプリケーションスロットは一時停止し、パーティションの期間中に遅延が増加します。
パーティションが修復したら、操作を再開する前に復旧を確認します。
bdr.node_slotsのラグメトリックを使用してキャッチアップの進行状況を監視し、すべてのスロットがstreamingに戻るまで待機します。パーティションウィンドウの競合率を確認します。 競合のモニタリング を参照してください。
競合のモニタリング#
ジオレプリケーションでは、同じ行が異なる場所で同時に更新される可能性があるため、競合の可能性が増加します。デフォルトでは、 PGDはlast-update-winsを使用して競合を解決します。タイムスタンプベースのリゾルバーは、ノード間のクロック同期に依存しています。すべてのノードでNTPまたはchronydを実行することにより、クロックスキューを最小限に抑えます。
bdr.conflict_history_summary
を定期的にチェックして、競合率の高いテーブルがないかどうかを確認します。
SELECT nspname, relname, conflict_type, count(*)
FROM bdr.conflict_history_summary
GROUP BY nspname, relname, conflict_type
ORDER BY count(*) DESC;
特定のテーブルでの高い競合率が持続する場合は、アプリケーションチームと再検討する価値があるアクセスパターンを示しています。永続的な競合は通常、デザインの問題です。ロケーションベースのデータの分割、追加専用パターン、またはCRDTデータ型への切り替えは、競合解決を調整するよりも長期的に効果的です。
競合リゾルバーの構成#
アクセスパターンの変更が現実的でなく、last-update-winsが特定のテーブルに対して誤った結果を生成する場合、
bdr.alter_node_set_conflict_resolver()
を使用してカスタムリゾルバーを構成します。使用可能なストラテジーはupdate_if_newer
デフォルト、skip 、およびerror
です。ファンクション呼び出しはレプリケートされないため、クラスター内の各ノードで実行します。最初にSELECT node_name FROM bdr.node_summary
を使用してノード名を確認します。
SELECT bdr.alter_node_set_conflict_resolver(
node_name => node1,
conflict_type => update_update,
conflict_resolver => error
);
すべての競合タイプにわたって現在のリゾルバー構成を確認するには
SELECT * FROM bdr.node_conflict_resolvers;
競合タイプとリゾルバーの完全なリストについては、 欠落列の競合の解決 を参照してください。