本記事では、Amazon Aurora Limitless Database の内部アーキテクチャについて解説します。特に、スケーラビリティと可用性を実現するための仕組みについて詳しく見ていきます。
Aurora Limitless Database を理解する上で、前提知識として、従来のデータベース運用における課題と、AWS が提供するマネージドデータベースサービスの利点を押さえておくと理解が深まります。
従来のデータベース運用では、以下のような課題がありました。
これらの課題を解決するために、AWS ではマネージドデータベースサービスを提供しています。マネージドデータベースサービスでは、AWS がデータベースの運用管理タスクを代行するため、ユーザーはデータベースの設計、開発、アプリケーションの構築といったコア業務に集中することができます。
Amazon Aurora も、このようなマネージドデータベースサービスの一つであり、高いパフォーマンス、スケーラビリティ、可用性、セキュリティ、そして運用管理の容易さを兼ね備えています。
データベース運用には、様々なタスクが存在します。特に、データベースの専門家が少ない環境や、システムやデータベースの数が多く管理対象が多い場合には、負担が大きくなってしまいます。
自社の責任範囲 | AWSの責任範囲 |
---|---|
クエリ作成 | High availability |
クエリ最適化 | コンフォーマンス |
スキーマ設計 | セキュリティ |
アプリケーションとの連携 | モニタリング パッチ適用 バックアップ & リカバリー |
パフォーマンスとスケーラビリティ | 可用性と耐久性 セキュリティ |
オペレーショナル・アナリティクス | 生成AI 規模に応じた管理能力 移行の容易性 |
マネージドデータベースは、これらのタスクの大部分を AWS 側に移譲することで、ユーザーは本来の業務に集中できるというコンセプトで開発されています。
Amazon Aurora は、以下の7つのコアバリューを基に開発が進められています。
特に、マネージャビリティという観点で運用管理の容易性を追求し、様々な機能のリリース、改善に取り組んでいます。近年では、生成系 AI の潮流も取り入れ、AI とのシームレスなインテグレーションも強化されています。また、既存環境から Aurora クラスターへの移行を容易にする仕組みや機能も提供されています。
Amazon Aurora は、マネージャビリティという観点で、様々な機能をリリースしています。データベースサービスではパフォーマンスやデータ容量に注目が集まりがちですが、RDS や Aurora は管理運用性の向上にも注力しています。
例えば、以下のような機能が挙げられます。
Amazon Aurora は、独自開発のストレージである「グローバー」を採用しています。「The log is the Database」という設計思想に基づき、データベースサーバーから送られてくる更新のログをすべて集め、データベースページとして再生成する仕組みです。これにより、従来のデータベースサーバーと比較して80%の Disk I/O の削減を実現しています。
グローバーストレージは、3つの Availability Zone (データセンターのクラスター) に2つずつ、計6つのデータのコピーを置くことで、1つの Availability Zone が消失した場合でも動作し続ける可用性の高い設計となっています。
また、グローバーストレージは単なるストレージではなく、コンピューティングの役割も担っています。そのため、Amazon Aurora とは、クエリを処理するエンジンだけでなく、グローバーとクエリを処理するノードを合わせて Aurora というサービスとして提供しています。
コンピューティングの面では、データベースをクラウド上でシームレスに動作させるために「カスピアン」と呼ばれる仕組みを開発しました。これは、Aurora Serverless v2 の裏側で動作している仕組みであり、ハイパーバイザーとヒートマネジメントを行うコントロールプレーンの総称です。
カスピアンの主な機能は以下の通りです。
ライブマイグレーションは、ダウンタイムやワークロードへの影響なく、どのインスタンスを移動させれば物理ハードウェアに空きが出るのか、どうすれば早くライブマイグレーションが完了してスペックアップができるのかを判断してコントロールプレーンが指示を出します。そのため、スケールアップのリクエストを出しているインスタンスをライブマイグレーションするという単純なロジックではなく、どれを移動させればすぐにスケールアップできるのかを考慮しています。
ライブマイグレーションの前後でバッファプールやコネクションのステートはすべてコピーされるため、アプリケーションは意識する必要がありません。
このキャパシティのコントロールは、リージョン単位で行われています。東京リージョンやノースバージニアといった単位でキャパシティのコントロールを行っており、この横軸がカスピアンインスタンスが稼働している物理ハードウェアで、青い点1個1個がカスピアンインスタンスを表しています。それぞれスケールアップ、スケールダウンの要求が来た時にリージョン全体として各ハードウェアのキャパシティが一定に保たれるように、稼働率が一定に保たれるようにライブマイグレーションを実施しています。
このように、マイグレーションを行うことでスケールアップのスロットリングがかからないよう、かつマイグレーションを高速に行えるように、常にインスタンスのキャパシティ管理を行っています。
これらのグローバーやカスピアンといった技術を用いて現在開発を進めているのが、新しい Aurora のシリーズである「Amazon Aurora Limitless Database」です。現在 Limited Preview 中で提供されています。
Aurora Limitless Database の開発を始めたきっかけは、Amazon Aurora でスケーラビリティは提供されているものの、やはり事業が続く中でデータサイズが増えていった場合や、アプリケーションの機能追加やイベント時にクエリがスパイクした場合などに、従来の1台のライターでは足りなくなるという状況が発生する可能性があることにあります。
このような時に、通常であればシャーディングと呼ばれる方法で、物理的に Aurora のクラスターを分割し、アプリケーション側でデータのアクセス先を振り分けます。しかし、シャーディングにはいくつかの問題点があります。
これらの問題点を解決するために、手作業でスクリプトを組んだり管理ツールを作成するケースも多いですが、それらのフィードバックをもとに、マネージドでシャーディングを実施するマネージドシャーディング機能を提供する、というコンセプトで開発されたのが Amazon Aurora Limitless Database です。
現在 PostgreSQL 互換のエンジンを提供しています。
このコンセプトは、1つのエンドポイントに対してクエリを投げるだけで、裏側で透過的にシャードの分割などを行い、アプリケーション側にカスタムロジックなどを組む必要がなくなり、メンテナンスも Aurora のプラットフォーム上で稼働するためマネージドで提供されます。そして何よりもパフォーマンス面では、この1つのエンドポイントだけで数100万トランザクション、そしてストレージに関してはペタバイトクラスのストレージを提供します。また、分散トランザクションや分散クエリといった複数のシャードにまたがったクエリもサポートします。
Limitless Database 内では、以下の3種類のテーブルが作成可能です。
シャーディングが行われるテーブルです。設定いただいたシャーディングキーを元に各シャードにデータが自動的に分散されます。
例えば、customer_id をキーとしたシャーディングの場合、customer_id が同じユーザーは、どのテーブルでも同じシャードに格納されます。これをコロケーションと呼びます。
更新量が少なく、テーブルのデータサイズが小さいものや、シャーディングキーの設定が難しいテーブルは、リファレンステーブルとして設定します。リファレンステーブルは、すべてのシャードに同じデータがコピーされます。
Limitless Database ではなく、通常の Aurora クラスターの中に作成される通常のテーブルです。
Limitless Database では、これらのテーブルをどのように作成していくかというと、まずセッション変数を定義します。
SET aurora_limitless.table_mode = 'shard';
上記のように、aurora_limitless.create_table_mode を用いて、今回はシャードテーブルを作成するため shard と指定します。
次に、どのカラムをシャーディングキーにするのかを指定してあげます。
CREATE TABLE users (
user_id INT PRIMARY KEY,
username VARCHAR(255),
email VARCHAR(255)
) PARTITION BY HASH(user_id);
今回は user_id をキーにシャーディングを行います。 複合キー、複数のカラムをシャーディングキーに設定することも可能です。
そして最後に、CREATE TABLE を実行します。この CREATE TABLE は PostgreSQL のものと全く同じ構文が使え、Limitless Database 用に構文の拡張は行われていません。そのため、特定のテーブルを Limitless Database として使いたい場合は、この2つのセッション変数を指定してあげるだけで、高速なテーブルが作成されます。
アプリケーション側にカスタムロジックなどを組む必要がなくなり、メンテナンスも、この後ご説明しますが、Aurora のプラットフォーム上で稼働するためマネージドで提供されます。
Limitless Database はサーバーレスアーキテクチャを採用しており、ユーザー側でインスタンスをプロビジョニングする必要はありません。最大キャパシティだけを設定すれば、その範囲内で自動的にシャードのスプリットやスケールアップ/ダウンが行われます。分散クエリや分散トランザクションといった複数のシャードにまたがった処理にも対応しています。
Limitless Database の内部アーキテクチャは、以下の2つのレイヤーで構成されています。
まず、分散トランザクションルーターは、単なるプロキシではなく、ユーザーに対して前述のエンドポイントを提供する役割と、どのシャードにどのデータが入っているかというメタデータを管理する役割を担います。
Limitless Database は時間ベースのトランザクションマネジメントを実行しており、そのための時刻の払い出しも行っています。
クエリの実行計画の解析もここでまず最初に行われ、マルチシャードクエリ、マルチシャードトランザクションになる場合は、トランザクションやクエリのコーディネーションをしたり、各シャードから返ってくるデータをアグリゲーションしたり DISTINCT として最終的にアプリケーションに返すといった処理を行います。
ユーザーから見ると、通常の Aurora のクラスターの下に Limitless Database のエンドポイントが追加され、クラスターエンドポイント、リーダーエンドポイント、カスタムエンドポイント、インスタンスエンドポイントに続く5つ目のエンドポイントとして、Limitless Database のシャードグループのエンドポイントが提供されます。アプリケーションからはこのエンドポイントに接続するだけで Limitless Database が使え、Aurora がサポートする機能の恩恵も受けられる仕組みです。
次に、データアクセスシャーディングのコンピューターレイヤーについて説明します。
このレイヤーはユーザーからは完全に隠蔽されており、直接見たりアクセスしたりすることはできません。ここもメタデータだけを保持しており、データ本体はグローバーストレージに格納されています。これは後で詳しくご紹介します。データにアクセスするためのシャードということで、データアクセスシャードと名前を呼んでいます。
さらに、このテーブルフラグメントは、サブレインジと呼ばれる単位に分割されます。このサブレインジに関してはユーザーから確認することができず、完全に内部的に分散処理を行うものになっています。これによって、シャード内での並列性の向上や、シャードスプリットが起こった時の高速なスプリット処理が可能になります。
Limitless Database では、ハッシュパーティショニングを採用しています。与えられたシャーディングキーの値をハッシュ関数にかけ、さらにハッシュのレンジに分割することで、単調増加する ID が発行されても特定のシャードに偏りにくい設計になっています。
データ本体をテーブルフラグメント、そしてメタデータをテーブルフラグメントリファレンスと呼び、実際にシャーディングされるのはテーブルフラグメントです。
ルーターのレイヤーも、データアクセスシャードのレイヤーも、データの実体は持っていません。データ本体はグローバーストレージにあり、その理由はこの後ご紹介します。
では、データアクセスシャードはなぜ「シャード」と呼ばずに、わざわざ「データアクセスシャード」と呼ぶのでしょうか。
それは、このレイヤーではメタデータだけを保持しており、実際のデータはグローバーにあるためです。データにアクセスするためのシャードであるという点を強調して、データアクセスシャードと命名しています。
シャードスプリット、つまり水平スケールはどのように行われるのでしょうか。基本的にはユーザー側で手動でスプリットすることもできますし、AWS のコントロールプレーンに任せることも可能です。
コロケーション設定されたテーブルに関しては、ちゃんと同じデータは同じシャードに分割されていきます。
テーブルスライスに関しては、ユーザー側で一切考慮する必要はなく、完全に内部的に分散処理を行うものになっています。これによって、シャード内での並列性の向上や、シャードスプリットが起こった時の高速なスプリット処理が可能になります。
Limitless Database は、Read Committed と Repeatable Read のトランザクションレベルに対応しています。
Read Committed アイソレーションレベルの場合、まずトランザクション1が SELECT 文を発行します。ルーターは T100 (便宜上 T100 という時間情報) を付与して各シャードにばら撒きます。必要なシャードは時刻情報 T100 の時点のリードビューを参照してクエリを返します。
次に別のトランザクションが実行され、今回は2つの UPDATE 文で、口座の中で金銭を動かすようなトランザクションを実行します。今回、シャード 619 を格納しているシャードが T118 の時点でプリペアが完了し、次に T112 の時点で 801 のシャードがプリペアが完了したという情報がルーターに返され、ルーターが T120 でコミットを打って良いという指示を出します。各シャードは T120 以上の時間に自分が含まれているか、かつグローバーにデータが完全に Durability な状態になっていると判断してコミットを実行します。
別のトランザクションは T116 という時間でクエリを発行していますが、T116 は T120 よりも前なので、このコミットされたデータは見せてはいけません。そのため、T116 の時点のリードビューを返します。
このように、マイクロ秒単位で処理が行われているため、多少時間がずれても数マイクロ秒のウェイトタイムで済みます。
Repeatable Read の場合も同様ですが、こちらは T100 の時刻情報がキープされています。そのため、SELECT 文を発行しても、T100 時点のリードビューを返します。
ここまで、内部の仕組みとどういったコンセプトで作ってきたのかをご紹介しました。
Limitless Database はまだ Limited Preview 中ではありますが、基本的にはライトスケーラビリティ、ストレージの性能やサイズが欲しい、もしくは MySQL や PostgreSQL のインターフェースが欲しい、リレーショナルデータベースが持つ複雑なトランザクション制御を使わないとダメ、そのトランザクション制御をデータベースのレイヤーに責務として持たせたい、もしくは JOIN で複数のテーブルをまとめなきゃいけない、各エンジンの組み込み関数やエクステンションを使いたい、という場合には Limitless Database が1つの選択肢になるかと思います。
今回限られた時間の中でお話しできなかったところ、Bounded Clock のトランザクション、ちょっと分かりにくかったというところがあればぜひお越しいただければ詳細解説したいと思います。
Amazon Aurora Limitless Database は、従来の Aurora の機能を継承しつつ、シャーディングを AWS によってマネージドで提供することで、スケーラビリティと可用性をさらに向上させたデータベースサービスです。
Aurora Limitless Database は、大規模なデータと高トラフィックを扱うアプリケーションに最適なデータベースサービスです。
AWSモダナイズ・スモールスタート開発支援、基幹業務システムのUI.UX刷新はお気軽にお問い合わせください。
スモールスタート開発支援、サーバーレス・NoSQLのことなら
ラーゲイトまでご相談ください
低コスト、サーバーレスの
モダナイズ開発をご検討なら
下請け対応可能
Sler企業様からの依頼も歓迎