Postgres-R

PostgreSQL July 17th, 2008

Twitter経由で知ったのだが、Postgres-Rというレプリケーション用の拡張がある。面白そうなので概要を読んだ。以下のように説明されている。

Postgres-R概要

Postgres-Rクラスタの構造

Postgres-Rは高速に相互接続された「何も共有しない」クラスタ群として設計されています。そのためギガビットイーサネットで接続されたAMD Opteronマシンのようなありふれたハードウェアで構築することができるクラスタになっています。Postgres-Rノード間の通信は全てレプリケーショングループを提供するグループコミュニケーションシステム(GCS)を介して行われます。ひとつのデータベースが各グループにレプリケーションされることになります。

グループに追加された最初のノードはまずレプリケーションを開始し、最初のデータを提供します。その後で他のノードがグループからのレプリケーションを受け付けることができるようになります。各ノードは稼動状態になる前にリカバリシステムにより初期化されます。リカバリ中にのみリカバリ提供側とリカバリを受ける側のノードとの違いを認識することができますが、通常は全てのノードは同じ内容です。

Postgres-Rノードのコンポーネント

Postgres-Rの主なコンポーネントはレプリケーションマネージャです。これはPostgres本体とは別に追加されたプロセスで、主にメッセージの調整を行い、グループコミュニケーションシステムやトランザクションを実行するバックエンドとの接続を調整します。

Postgresにはトランザクションを扱うバックエンドのプロセスがあります。それぞれのバックエンドは一度にひとつのトランザクションしか扱うことができません。リモートのノードからのトランザクションをリプレーするために、レプリケーションマネージャはレプリケーションマネージャの管理下にありクライアントとの接続はない「リモートバックエンド」というものを開始します。それに対して、ローカルのトランザクションを扱っているバックエンドのプロセスたちは「ローカルバックエンド」と呼ばれ、クライアントと直に接続されています。

レプリケーションされたトランザクションのライフサイクル

Read-onlyのトランザクションはローカルで扱われ、通常のPostgresの単一ノードの操作と何ら変わらないものとみなされます。トランザクションがデータを書き込むと(UPDATE、INSERTまたはDELETEなどのSQLコマンド)、新しいデータがすぐに書き込みセットとして集められます。ローカルバックエンドはトランザクションを処理し続け、クライアントからコミットリクエストを受け取るまで書き込みセットに変更を集め続けます。

クライアントにコミットを返す前に、ローカルバックエンドは書き込みセットをレプリケーションマネージャに送ります。レプリケーションマネージャは順に並べられたグループコミュニケーションシステムのチャンネルを使ってそれを順々に全ての他のノードに送信します。トランザクションを開始したローカルバックエンドは、書き込みセットが戻されたところでコミットできるようになります。自分でもリプレイするように書き込みセットを受け取った他のノードでは、レプリケーションマネージャがリモートバックエンドのプロセスを開始して書き込みセットをそれに引き渡します。するとリモートバックエンドは書き込みセットにあるデータからトランザクションを自分でもリプレイします。

衝突の扱い

Postgres-Rでは書き込みトランザクションはシリアライズされて元と同じ順序でレプリケーションクラスタを共有する各ノードに配信されます。これによりノード間の同期と一貫性が保証されます。トランザクションがあるノードに正常にコミットされたならば、他の全てのノードにも同じくコミットされます。そのため、他のノードの処理を待つことなくそれぞれのノードがフルスピードで稼動することが可能になります。ネットワークのトラヒックを可能な限り抑えるためにトランザクションの変更だけが転送されます。

この手法はシリアライズ可能なPostgresのトランザクションレベルで最大の効果を発揮します。READ COMMITTEDモードでは通常の単一ノードの運用時と同じトランザクションセマンティクスを提供するためにロックもレプリケーションされます。そのためレプリケーションするデータベースシステムのほとんどでボトルネックとなるであろうネットワークトラヒックの増大を引き起こします。

というわけで、実際の動作をさせてみないとなんともいえないが、面白そうな存在なのでちょくちょくチェックする。

Leave a Reply