レプリケーションモード
PatroniはPostgreSQLストリーミングレプリケーションを使用します。ストリーミングレプリケーションの詳細については、 Postgres documentation _を参照してください。デフォルトでは、Patroniは非同期レプリケーション用にPostgreSQLを構成します。レプリケーションスキーマの選択は、ビジネスの考慮事項によって異なります。非同期レプリケーションと同期レプリケーションの両方、および他のHAソリューションを調査して、どのソリューションが最適であるかを判断します。
非同期モードの耐久性
非同期モードでは、クラスターは可用性を保証するために、コミットされたトランザクションの一部を失うことができます。プライマリサーバーに障害が発生するか、他の理由で使用できなくなると、Patroniは十分に正常なスタンバイをプライマリに自動的にプロモートします。そのスタンバイにレプリケートされていないトランザクションは、プライマリ上の/"フォークされたタイムライン"に残り、事実上回復不能です[1]_。
失われる可能性のあるトランザクションの量は、 maximum_lag_on_failover パラメーターを介して制御されます。プライマリトランザクションログの位置はリアルタイムでサンプリングされないため、実際には、フェールオーバーでの損失データの量は、ワーストケースになります。トランザクションログの maximum_lag_on_failover バイトと、最後の ttl 秒に書き込まれた量 loop_wait /2秒平均的な場合)。ただし、一般的な定常状態のレプリケーション遅延は1秒未満です。
デフォルトでは、リーダー選挙を実行するときに、パトローニはレプリカの現在のタイムラインを考慮しません。これは、場合によっては望ましくない動作である可能性があります。 check_timeline パラメーターの値を true に変更することにより、元のプライマリと同じタイムラインを持たないノードが新しいリーダーになるのを防ぐことができます。
PostgreSQL同期レプリケーション
PatroniではPostgresの synchronous replication _を使用できます。同期レプリケーションは、接続しているクライアントに成功して返す前に、書き込みがセカンダリに書き込まれることを確認することにより、クラスター全体の一貫性を保証します。同期レプリケーションのコスト 書き込み時の待機時間の増加とスループットの低下。このスループットは、ネットワークパフォーマンスに完全に基づいています。
ホスト型データセンター環境AWS、Rackspace、または制御していないネットワークなどでは、同期レプリケーションにより書き込みパフォーマンスの変動が大幅に増加します。フォロワーがリーダーからアクセスできなくなると、リーダーは事実上読み取り専用になります。
単純な同期レプリケーションテストを有効にするには、YAML構成ファイルの parameters セクションに次の行を追加します。
synchronous_commit: "on"
synchronous_standby_names: "*"
PostgreSQL同期レプリケーションを使用する場合、少なくとも3つのPostgresデータノードを使用して、1つのホストに障害が発生した場合の書き込み可用性を保証します。
PostgreSQL同期レプリケーションを使用しても、すべての状況でトランザクション損失ゼロを保証するものではありません。プライマリと、現在同期レプリカとして機能しているセカンダリに同時に障害が発生すると、すべてのトランザクションが含まれていない可能性がある3番目のノードが昇格します。
同期モード
コミットされたトランザクションの損失が許容されないユースケースでは、Patroniの synchronous_mode をオンにすることができます。 synchronous_mode がオンになっている場合、Patroniは、スタンバイにクライアント[2]_に成功したコミットステータスを返した可能性のあるすべてのトランザクションが含まれていることが確実でない限り、スタンバイをプロモートしません。これは、一部のサーバーが利用可能な場合でも、システムは書き込みに利用できない場合があることを意味します。システム管理者は、トランザクション損失が発生した場合でも、手動フェイルオーバーコマンドを使用してスタンバイを昇格させることができます。
synchronous_mode をオンにしても、すべての状況でのコミットのマルチノードの耐久性は保証されません。使用可能な適切なスタンバイがない場合、プライマリサーバーは書き込みを受け入れますが、レプリケーションは保証しません。このモードでプライマリに障害が発生すると、スタンバイは昇格しません。プライマリであったホストが復帰すると、システム管理者が手動フェイルオーバーを実行しない限り、自動的に昇格します。この動作により、2ノードクラスターで同期モードを使用できるようになります。
synchronous_mode がオンで、スタンバイがクラッシュすると、パトロニの次の反復が実行され、プライマリをスタンドアロンモードに切り替えるまで、コミットがブロックされます書き込みの最悪の場合の遅延は ttl 秒、平均的な場合は loop_wait / 2秒。スタンバイを手動でシャットダウンまたは再起動しても、コミットサービスの中断は発生しません。スタンバイは、PostgreSQLのシャットダウンが開始される前に、同期スタンバイ業務から自分自身を解放するようにプライマリに信号を送信します。
各書き込みが少なくとも2つのノードに永続的に保存されることを保証する必要がある場合は、 synchronous_mode に加えて synchronous_mode_strict を有効にします。このパラメーターは、使用可能な同期スタンバイ候補がない場合、Patroniがプライマリで同期レプリケーションをオフにしないようにします。欠点として、プライマリはPostgresトランザクションが明示的に synchronous_mode をオフにしていない限り書き込みに利用できず、少なくとも1つの同期レプリカが登場するまで、すべてのクライアントの書き込み要求をブロックします。
nosync タグをtrueに設定することにより、スタンバイが同期スタンバイにならないようにできます。これは、遅いネットワーク接続の背後にあり、同期スタンバイになるとパフォーマンスの低下を引き起こすスタンバイに設定することをお勧めします。タグ nostream をtrueに設定しても、同じ効果があります。
同期モードは、 patronictl edit-config コマンドまたはPatroni RESTインターフェイスを使用してオンおよびオフにできます。手順については、 patronictl edit-config を参照してください。
注 PostgreSQLで同期レプリケーションが実装される方法のため、 synchronous_mode_strict を使用する場合でもトランザクションが失われる可能性があります。レプリケーションの確認を待機しているときにPostgreSQLバックエンドがキャンセルされると、クライアントのタイムアウトまたはバックエンドの障害によるパケットキャンセルの結果、トランザクションの変更が他のバックエンドに表示されるようになります。このような変更はまだ複製されていないため、スタンバイプロモーションの場合に失われる可能性があります。
同期レプリケーションファクター
パラメーター synchronous_node_count は、Patroniが同期スタンバイデータベースの数を管理するために使用されます。デフォルトでは 1 に設定されます。 synchronous_mode が off に設定されている場合、効果はありません。有効にすると、Patroniはパラメーター synchronous_node_count に基づいて同期スタンバイデータベースの正確な数を管理し、メンバーが参加および離脱するときにPostgreSQLのDCSおよび synchronous_standby_names の状態を調整します。パラメーターが資格のあるノードの数より大きい値に設定されている場合、パトローニによって自動的に削減されます。
同期ノードの最大遅延
デフォルトでは、Patroniは、その前に他のノードがある場合でも、 pg_stat_replication ビューによると synchronous として宣言されたノードに固執します。これは、 synchronous_standby_names の変更の数を最小限に抑えるために行われます。この動作を変更するには、 maximum_lag_on_syncnode パラメーターを使用できます。これは、レプリカが/"同期/"と見なされるまでのどのくらいの遅延を制御します。
Patroniは、複数のスタンバイがある場合に最大レプリカLSNを利用します。それ以外の場合、リーダーの現在のwal LSNを使用します。デフォルトは -1 であり、値が 0 以下に設定されている場合、Patroniは同期の不健全なスタンバイをスワップするアクションを実行しません。トランザクション量が多いときにPatroniが同期スタンバイを頻繁にスワップしないように、十分な高い値を設定してください。
同期モードの実装
同期モードの場合、Patroniは、最新のプライマリおよび現在の同期スタンバイデータベースを含むDCS /sync キーで同期状態を維持します。この状態は、次の不変条件を保証するために厳密な順序制約で更新されます。
ノードは、書き込みトランザクションを受け入れることができるときは常に、最新のリーダーとしてマークされる必要があります。 Patroniがクラッシュするか、PostgreSQLがシャットダウンしていない場合、このインバリアントの違反が発生する可能性があります。
ノードは、DCSの
/syncキーで同期スタンバイとして公開されている限り、PostgreSQLで同期スタンバイとして設定する必要があります。リーダーまたは現在の同期スタンバイではないノードは、自分自身を自動的に昇格させることはできません。
Patroniは、 synchronous_standby_names への synchronous_node_count パラメーターに基づいて、1つ以上の同期スタンバイノードのみを割り当てます。
HAループ反復ごとに、Patroniは同期スタンバイノードの選択を再評価します。同期スタンバイノードの現在のリストが接続され、同期ステータスの削除を要求していない場合、選択されたままです。それ以外の場合、レプリケーションで最も進んでいる同期に使用可能なクラスターメンバーが選択されます。
例
DCSの /config キー
synchronous_mode: on
synchronous_node_count: 2
...
DCSの /sync キー
{
"leader": "node0",
"sync_standby": "node1,node2"
}
postgresql.conf
synchronous_standby_names = 'FIRST 2 (node1,node2)'
上記の例では、ノード node1 および node2 のみが同期であることが知られ、プライマリ node0 に障害が発生した場合に自動的に昇格できます。
クォーラムコミットモード
PostgreSQL v10から、Patroniはクォーラムベースの同期レプリケーションをサポートしています。
このモードでは、PatroniはDCSの同期状態を維持します。これには、最新の既知のプライマリ、クォーラムに必要なノードの数、および現在クォーラムに投票する資格のあるノードが含まれます。定常状態では、クォーラムに投票したノードがリーダーであり、すべての同期スタンバイです。この状態は、ノードのプロモーションと synchronous_standby_names に関する厳密な順序制約で更新され、クォーラムを達成できる投票者のサブセットに、最後に成功したコミットを持つ少なくとも1つのノードが常に含まれるようにします。
HAループの反復ごとに、Patroniはノードの可用性と要求されたクラスター構成に基づいて、同期スタンバイの選択とクォーラムを再評価します。 9.6以降のPostgreSQLバージョンでは、レプリケーションがリーダーに追いつくと、すべての対象ノードが同期スタンバイとして追加されます。
クォーラムコミットは、1つのスタンバイへの複製のより高いレイテンシを他のスタンバイで補うことができるため、通常動作中でも最悪の場合のレイテンシを削減するのに役立ちます。
クォーラムベースの同期モードは、 patronictl edit-config コマンドまたはPatroni RESTインターフェイスを介して synchronous_mode を quorum に設定することにより、有効にできます。手順については、 synchronous_mode を参照してください。
synchronous_node_count 、 maximum_lag_on_syncnode 、 synchronous_mode_strict のような他のパラメーターは、 synchronous_mode=on と同じように動作し続けます。
例
DCSの /config キー
synchronous_mode: quorum
synchronous_node_count: 2
...
DCSの /sync キー
{
"leader": "node0",
"sync_standby": "node1,node2,node3",
"quorum": 1
}
postgresql.conf
synchronous_standby_names = 'ANY 2 (node1,node2,node3)'
プライマリ node0 に障害が発生した場合、上記の例では、 node1 、 node2 、 node3 のうちの2つが最新のトランザクションを受信しますが、どれがどれであるかはわかりません。ノード node1 が最新のトランザクションを受信したかどうかを判断するには、そのLSNと、 node2 および node3 のうちの node0 の1つのノード /sync キーの quorum=1 のLSNと比較する必要があります。 node1 がそれらの少なくとも1つの背後にない場合、 node1 が昇格した場合にユーザーに見えるデータの損失がないことを保証できます。