概要
- 2022年12月ごろに GCP の AlloyDB for PostgreSQL が GA したという発表がされました。
- こちらサービスの紹介については以下の記事を参照いただけると幸いです。
- 今回は、この AlloyDB について公式に公表されている内容からその仕組みについてまとめていこうと思います。
- AlloyDB とは、標準的な PostgreSQL よりもトランザクションワークロードで4倍、分析クエリで最大100倍以上早いと謳っています。
- そんな AlloyDB for PostgreSQL の内部について公開されている情報からその仕組みついてをまとめていきます。
コンピューティングとストレージの分離
- AlloyDB for PostgreSQL は、コンピューティング部分とストレージ部分を切り分けているようです。
- 下記の図を見ると分かるように、PostgreSQL 用に最適化された Intelligent Database Storage Engine というものを導入することで、I/Oのボトルネックを減らし、かつログ処理システムを使用することでデータベースに対する操作をストレージレイヤーにオフロードすることができるようです。
- また、ストレージとコンピュート部分が切り離されていることで、ブロックストレージをログ処理とは別にスケーリングできるというのもメリットになります。
なぜコンピュート部分とストレージ部分を切り分けているのか
- なぜコンピュート部分とストレージ部分を切り分けているのか、それは、従来のモノリシック設計に対する問題点があったからです。
- ここで言っている、モノリシックな設計というのはストレージとコンピューティングリソースを1台のマシンに配置していることを指します。
- 例えばですが、今まで動いていたワークロードに耐えられなくなり、より多くのストレージ容量やコンピューティング処理に対するパフォーマンスが必要となった場合、強力なサーバーへ移行するか、ディスクを追加して、システムをスケールアップしないといけません。
- これには欠点もあり、例えば物理的にサーバの増強やディスク追加が無理になったり、費用対効果的によろしくない状態になる可能性も秘めていますよね。
- そうなった場合には、レプリケーションを使用して、複数の読み取り専用のコピーを作成したりすると思います。
- ただ、このアプローチにも限界があり、フェイルオーバー時間は、データベースの負荷や構成に依存するのでいつ終わるか検討がつきません。長くなるかもしれないし、そうではないかもしれない。
- さらに読み取り専用のコピーは遅れが発生する可能性もありますし、読み取り専用インスタンスの容量のスケーリングとラグの管理が複雑化します。
- なので、ストレージとコンピューティングが密接に結合されたモノリシックな設計だと仕組み上、柔軟性にかけるということです。
AlloyDB の場合だと・・?
- 単一の仮想マシンの容量を超えスケーラビリティを高めるために、複数の読み取り専用インスタンスを追加して、読み取り専用クエリ処理でプライマリとなるデータベースインスタンスを保護できます。
- ストレージ部分は、複数のゾーンに分散され任意のサーバからアクセスできます。
- なので、各読み取り専用インスタンスは独自のストレージを必要としないため、低コストで最新の読み取り専用インスタンスをすぐに構築することができます。
AlloyDB 設計の概要
- AlloyDB ストレージ部分は、以下の3つの主要部分で構成される分散システムのようです。
1: 超高速に WAL を書き込みのための低遅延のログストレージサービス
2: WAL レコードを処理し、データベースブロックを生成するログ処理サービス(LPS)
3: ゾーンストレージに障害が発生した場合でも耐久性を保証する、シャード化されたリージョンブロックストレージ
-
以下の図は、ログ処理サービスと、PostgreSQL データベースレイヤーおよび永続ストレージとの統合の概念的ものを示しています。
-
プライマリデータベースインスタンスは、WAL ログエントリを保持し、データベースの操作(INSERT/DELETE/UPDATE など) を低レイテンシのリージョンログストアに反映しておきます。
-
そこから、ログ処理サービス (LPS) がこれらの WAL レコードを使用し、非同期処理を実行します。
-
LPS は、WAL レコードのセマンティクスと PostgreSQL のストレージ形式を認識しているため、WAL レコードによって記述された操作を継続的に再生されます。
-
各ログレコードは、各ゾーンで1回だけ処理されるため、最新のデータデータベースブロックがシャード化された地域ストレージシステムに反映されます。
-
そこから、レプリカインスタンス(読み取り専用)のローカルキャッシュを最新の状態に保つために、WAL レコードをプライマリからレプリカインスタンスにストリーミングして、最近の変更について通知します。
-
なぜ通知するのかというとブロックの変更に関するこの情報がないと、レプリカインスタンスにキャッシュされたブロックが勝手に古くなる可能性があるためです。
(画像引用元: https://cloud.google.com/blog/products/databases/alloydb-for-postgresql-intelligent-scalable-storage?hl=en)
この仕組みの利点ってなんだ?
-
LPS によって、ワークロードパターンに基づいてスケールアウトし、必要に応じてログを処理するためのコンピューティングリソースを透過的に追加することで、ホットスポットを回避できます。
-
ログプロセッサは、共有リージョンストレージに接続されているため、データをコピーする必要なく、スケーリングできます。
-
複数のゾーンにまたがるすべてのブロックを同期的にレプリケートすることにより、ゾーンの障害からシステムを自動的に保護します。
-
この設計の場合、データベースレイヤーにチェックポイントを設定する必要はなく、データベースブロックをストレージレイヤーに送信する理由はありません。
-
これにより、データベース層がクエリ処理のタスクに集中できるので、データベースとストレージ層の間のネットワークを効率的に使用できるようになります。
-
低遅延のリージョンログストレージを使用することで、トランザクションコミット操作の場合に WAL ログレコードをすばやくフラッシュすることができます。
-
ストレージサービスは、あるゾーンのあるブロックという形で提供できるので、データベースレイヤーの読み取りレプリカインスタンスをストレージサービスにアタッチし、データベースのコピーを必要とせずにクエリを処理できます。(欲しい読み取りレプリカインスタンス数だけ)
-
さらに、読み取りレプリカインスタンスが高速に作成できるのは必要に応じてストレージレイヤーからデータを段階的に読み込むことができるためです。
-
ログ処理サービスは操作中に WAL ログレコードを継続的に再生するため、再起動復旧中に処理する必要がある先行書き込みログの量は最小限なので、システムの再起動が高速化されています。なぜ高速化できるのかというと、WAL 関連の回復作業が最小限に抑えられるためです。
ストレージレイヤの弾力性
- 要求の厳しいワークロードの場合、LPS プロセスが1つしかないとスケーラビリティに問題が生じる可能性が発生しますよね。
- なぜかというと、LPS が WAL レコードを継続的に再生するだけでなく、プライマリインスタンスと複数の読み取りレプリカ インスタンスの両方からの読み取り要求を処理する必要があるためです。
- この問題に対処するために、データベースはブロックのグループに水平に分割されます。(シャード)
- シャードと LPS リソースはどちらも、水平方向に独立してスケーリングするようです。
- すべてのシャードは常に 1 つの LPS に割り当てられますが、各 LPS は複数のシャードを処理できます。
- どうに動くかというと、システム全体の負荷が増加し、事実上すべてのシャードが以前よりも多くのリクエストを受け取った場合に、ストレージ層は LPS インスタンスの数を増やすことがことができます。
- この時、新しく作成されたログ処理サーバーインスタンスは、シャードの一部を引き継いで既存のインスタンスをオフロードするようです。
(画像引用元: https://cloud.google.com/blog/products/databases/alloydb-for-postgresql-intelligent-scalable-storage?hl=en)
ストレージレイヤーのレプリケーションとリカバリ
- AlloyDB は、ゾーン障害(データセンター)が発生した場合でも、データの耐久性と高いシステム可用性を提供しています。
- すべての AlloyDB インスタンスのストレージレイヤーは3つのゾーンに分散されています。
- 各ゾーンにはデータベースの状態の完全なコピーがあり、低レイテンシのリージョンログストレージシステムから WAL レコードを適用することで継続的に更新されます。
(画像引用元: https://cloud.google.com/blog/products/databases/alloydb-for-postgresql-intelligent-scalable-storage?hl=en)
参考文献