Firestore を使用したスケーラブルなアプリケーションの構築

このドキュメントでは、Firestore を使用して大規模なアプリケーションを構築する場面について説明します。このドキュメントでは、大規模なアプリケーションのデータベース システムを管理するインフラストラクチャ管理者向けのソリューションについて説明します。Firestore を他の Google Cloud プロダクトと一緒に使用すると、データベースのプロビジョニングとメンテナンスが簡素化されるため、容量計画ではなくアプリの開発に集中できます。

Firestore の機能と制限事項

Firestore は、モバイル アプリケーションとウェブ アプリケーション向けに設計されており、柔軟で非リレーショナルなスキーマを持つ階層的なトランザクション データを格納するのに適しています。Firestore をデータベース ソリューションの候補として評価するときは、その割り当てと上限がユースケースに適切であることを確認してください。Firestore は汎用性があり、多くの場合に適用可能ですが、状況によっては、他の Google Cloud データベース プロダクトのほうが適している場合があります。Firestore とこれ以外のソリューションのどちらを使用するかを決定する際は、次の要素を考慮してください。

ストレージ

Firestore では、データ ストレージを容量の上限なしにホストできます。キロバイト単位からペタバイト単位までのデータ量を同じ方法で処理します。パフォーマンスに影響は与えません。

リアルタイム アップデート

Firestore は、クライアントがドキュメントをリッスンし、クエリを使用してリアルタイムの更新を取得できるようにすることで、リアルタイム アップデートを実現します。単一のドキュメントの現在のコンテンツですぐにドキュメント スナップショットを作成するコールバックを指定します。ドキュメントのコンテンツが変更されるたびに、別の呼び出しによってドキュメント スナップショットが更新されます。

オフライン データの永続性

Firestore では、オフライン データの永続性と、モバイル クライアントおよびウェブ クライアントの完全なオフライン サポートを実現しています。オフライン時にデータにアクセスして更新し、オンラインに復帰した際に変更を自動的にクラウドと同期できます。組み込みのオフライン サポートは、ローカル キャッシュを活用してデータを提供、保存するため、ネットワークのレイテンシやインターネット接続に関係なく、アプリの応答性は維持されます。

トランザクション

Firestore は、マルチドキュメントで ACID 準拠のトランザクションをサポートしています。ACID という用語は、原子性、整合性、独立性、耐久性の略です。

クエリ

Firestore では、データベース全体での強整合性を確保したクエリが提供されます。Firestore では、プライマリ インデックスに加えて、セカンダリ インデックスと複合インデックスがサポートされており、クエリでリクエストするアイテムの場所をすばやく検索できます。

Firestore のクエリには次のような制限があります。

  • Firestore は非リレーショナル データベースであるため、SQL セマンティクスを使用するリレーショナル スキーマやクエリはサポートされていません。特に Firestore では、結合オペレーション、複数のプロパティの不等式フィルタリング、サブクエリの結果に基づくデータのフィルタリングはサポートされていません。
    • アプリで SQL サポートが必要な場合、非水平スケーリングには Cloud SQL を使用します。
    • アプリで SQL サポートが必要な場合、大規模な水平スケーリングやグローバル スケーリングには Cloud Spanner を使用します。
  • Firestore は、オンライン トランザクション処理(OLTP)に最適化されています。

セキュリティ

Firestore は、データをディスクに書き込む前に、自動的にすべてのデータを暗号化します。Firestore は、使用されているクライアント ライブラリに応じた以下の方法で、堅牢なアクセス管理と認証を提供します。

自動スケーリング

Firestore は、ダウンタイムなしで自動的にスケールアップします。このスケーリング メカニズムにより、Firestore は 1 秒あたり数千のリクエストと数百万の同時接続を処理できます。料金は、ストレージのサイズとオペレーション数に基づき、実際の使用量に対してのみ課金されます。詳しくは、Firestore の料金をご覧ください。

Firestore の自動スケーリングには次の上限があります。

  • Firestore のネイティブ モードでは、ドキュメントの更新オペレーションを、1 秒あたり最大 10,000 件の書き込みと 100 万を超える接続までスケールできます。アプリがこの書き込みレート制限を超える場合は、1 秒あたり数百万の書き込みまでスケールアップできる Datastore モードを使用することをおすすめします。これらのモードの違いについては、ネイティブ モードと Datastore モードからの選択をご覧ください。
  • Firestore は大規模なオペレーションを処理できます。ただし、レプリケーションやトランザクションなどの複雑な機能をサポートするために、Firestore にはいくつかのトレードオフがあり、そのため非常に高い負荷を処理するアプリでパフォーマンスが下がる可能性があります。
    • アプリの書き込みが非常に多い場合は、Cloud Bigtable を使用し、トランザクションとセカンダリ インデックスの優先度を下げてデータ取り込み機能を高めることを検討してください。
    • アプリがユーザーに同じ情報を頻繁に表示する場合(ゲームでのプレーヤー リーダーボードなど)、クライアント側でキャッシュすることで、サーバーへの不要なリクエストを回避して負荷を減らすことを検討してください。

レイテンシ

Firestore では、レイテンシよりも耐久性と可用性が重視されており、クロスリージョンまたはクロスゾーンでの同期書き込みが行われます。アプリでデータの読み取り時または書き込み時に一貫して 10 ミリ秒未満のレイテンシが求められる場合、Memorystore for Redis などのインメモリ データベースの使用を検討してください。

冗長性と可用性

Firestore では、複数のロケーションでのさまざまなレプリケーション メカニズムに基づく、次のレベルの冗長性が提供されています。

  • リージョン レプリケーションは、書き込みレイテンシを低くすることの優先度が高い場合に最適です。リージョン レプリケーションを使用すると、データは同じリージョン内に複製されます。レイテンシを最小限に抑えるため、同じリージョンにアプリを配置することをおすすめします。
  • マルチリージョン レプリケーションは、可用性を確保することの優先度が高い場合に最適です。マルチリージョン レプリケーションを使用すると、データは少なくとも 2 つの異なるリージョンにある複数のゾーンで複製されるため、リージョンで障害が発生してもデータベースの復元性が確保されます。マルチリージョン レプリケーションにより可用性と冗長性は高まりますが、書き込みレイテンシが高くなります。図 1 に示されているように、監視ノードが 3 番目のリージョンに配置され、複製された 2 つのリージョン間のタイブレーカーとして機能します。

マルチリージョン データベースのレプリケーション スキーム。

図 1. Firestore でのマルチリージョン データベースの図。

クライアント ライブラリ

モバイル クライアントとウェブ クライアントは、Android、iOS、ウェブのクライアント ライブラリを使用して Firestore に直接アクセスできます。また、Firestore は Firebase プラットフォームとシームレスに統合されており、Crash Reportingユーザー認証メッセージ配信ユーザー イベント分析などの機能を利用できます。

Firestore を使用する場面

Firestore の機能は、以下のような幅広いユースケースに適しています。

  • ユーザー プロフィール: ユーザー プロフィールを管理し、ユーザーの過去のアクティビティや好みに基づいてユーザー エクスペリエンスをカスタマイズします。Firestore の柔軟なスキーマを使用して、ユーザー プロフィールの構造を発展させることができます。たとえば、新しいプロパティを追加して、アプリの新機能をサポートできます。スキーマの変更はダウンタイムなしで行われ、ユーザー数が増えてもパフォーマンスは低下しません。
  • リアルタイム インベントリ: Firestore の豊富でネストされたオブジェクトを使用して、構造を過度に特殊化することなく、さまざまなプロダクトの多種多様で膨大な量のスパースデータを保存できます。たとえば、小売店の商品カタログを作成できます。
  • ユーザー セッション管理: ACID トランザクションに対する Firestore のサポートにより、ユーザーはトランザクションが完了するまで 1 つ以上のドキュメントをロックできます。たとえば、小売取引用のショッピング カートや、イベント予約のためのマルチパート処理フォームを作成できます。
  • 状態のミューテーション: Firestore の ACID トランザクションを使用して、多数の同時接続ユーザーにミューテーションを反映させることができます。たとえばゲームアプリで、すべてのプレーヤーに対して一貫した状態を維持できます。
  • 永続的なライトスルー キャッシュ: Firestore の高可用性と耐久性により、永続的な状態が維持され、アプリのクラッシュによるデータ損失を防ぐことができます。Firestore には、使いやすい Key-Value ストアのような機能があります。ただし、Firestore には、有効期間(TTL)やキャッシュ有効期限のメカニズムは組み込まれていません。
  • クロスデバイスでのデータ同期: Firestore のリアルタイム アップデートにより、接続されているすべてのデバイスで、常に最新の状態が表示されます。たとえば、Firestore は、共同編集可能なマルチユーザー モバイルアプリや、複数のデバイスから接続するアプリに一貫した状態を提供します。
  • IoT 管理とアセット トラッキング: Firestore のオフライン データの永続性を使用すれば、デバイスのネットワーク接続が失われた場合でもデータポイントを記録できます。たとえば、モバイル デバイスや自動車のリアルタイム GPS トラッキングを設定できます。
  • リアルタイム機能: Firestore のリアルタイム アップデートで、リアルタイムの分析とメッセージングを設定できます。インタラクティブなビジュアル ダッシュボードなど、視覚的なグラフやチャートを最新の状態に保ち、ライブ ディスカッション フォーラムやチャットルームを設定できます。
  • 分散カウンタ: 分散カウンタを設定して、特定の項目に関連した投稿やお気に入りに関する高評価の数など、ドキュメント操作を表示できます。

リファレンス アーキテクチャ

このセクションでは、Firestore と他の Google Cloud プロダクトを組み合わせた大規模なウェブアプリを構築するためのリファレンス アーキテクチャについて説明します。たとえば、次のようなものがあります。

  • 毎日のエクスポート
  • キャッシュ
  • データ処理
  • 機械学習用のモデルのトレーニング

このようなアーキテクチャは規範的なものではありません。それよりも、スケーラブルなウェブアプリを構築する際に、Firestore を幅広く使用できることをわかりやすく示すことを目的としています。アーキテクチャを再編成および調整して、要件を満たす独自のウェブアプリを構築できます。

ゲーム

このユースケースでは、ゲーム用プラットフォームで数万人のプレーヤーによる同時アクセスがサポートされています。このゲームのフロントエンド サービスは、Firestore を使用して、何十億ものドキュメントを階層構造のゲーム世界の状態データとともに保存します。Firestore には、ユーザー構成、パーティー メンバー、ギルド、フレンドリスト、プレゼンス データなどのユーザーデータも保存されます。このユースケースでは、以下のような他の Google Cloud プロダクトが組み込まれています。

  • Spanner は、世界中の大規模なプレーヤー集団のインベントリやマッチ履歴を保持できる、グローバルに整合性のあるデータベースを提供します。
  • 頻繁に使用されるデータへのアクセスを高速化するために、Memorystore for Redis にリージョン インメモリ キャッシュがデプロイされます。
  • イベントは Bigtable に記録されます。デベロッパーやサポート スタッフは、トラブルシューティングのためにそのイベントにアクセスできます。
  • フロントエンド データベースとバックエンド データベースのデータは、データ分析パイプラインを実行するために、BigQuery に定期的にインポートされます。このパイプラインは、ゲームのコミュニティに影響が及び、プレーヤーが追放される前に悪用を検出し、更新が必要なゲームプレイの仕組みを明らかにするために役立ちます。

図 2 は、ゲームのユースケースのアーキテクチャを示しています。

ゲームのユースケースのアーキテクチャ。

図 2. ゲーム プラットフォームのアーキテクチャの例。

モノのインターネット

このユースケースでは、インタラクティブ ウェブアプリが、モノのインターネット(IoT)デバイスによって生成されたリアルタイムのテレメトリー情報を表示します。このデバイスはユーザーの体温と心拍数を定期的に測定および収集し、このデータを次のように処理します。

  1. 各測定値が、MQTT ブリッジおよび HTTP ブリッジを介して IoT Core にすぐに送信されます。
  2. IoT Core は、各測定値を個別のメッセージとして Pub/Sub に公開します。
  3. Pub/Sub メッセージが Cloud Functions の関数をトリガーし、未加工のメッセージから関連情報を抽出して、その結果を Firestore で長期間保存します。
  4. Firebase Hosting でホストされ、Angular をベースとしたインタラクティブなウェブ ユーザー インターフェースが、Firestore から直接更新をリッスンします。各更新は自動的にウェブ ユーザー インターフェースに push され、最新の情報がリアルタイムで可視化されます。

図 3 は、このシナリオにおけるテレメトリー情報のデータ パイプラインを示しています。

IoT アプリのユースケースのアーキテクチャ。

図 3. IoT アプリのアーキテクチャの例。

小売

このユースケースでは、小売プラットフォームが初回購入者に向けて、さまざまなメディアを通じておすすめの商品情報を提供します。ウェブアプリが、参照 URL、地理的リージョン、デバイスタイプなど、オンライン ユーザーに関するライブデータ ポイントを記録し、収集したデータを次のように Firestore に書き込みます。

  1. 新しいレコードが作成されるたびに、Cloud Functions のデータ パイプラインがトリガーされ、ユーザーデータが BigQuery にコピーされます。
  2. Spark MLlib で実装され、Dataproc にデプロイされるレコメンデーション エンジンが、BigQuery に保存されているライブ ユーザーデータと Cloud SQL に保存されている商品メタデータでトレーニングされます。
  3. このレコメンデーション エンジンは、おすすめの商品情報の提供で次の予測を行います。
    • Firestore に書き込まれ、オンライン ユーザーのデバイスに自動的に push されるリアルタイム予測。
    • メールサービスでオフライン ユーザーに送信されるバッチ予測。

図 4 は、小売プラットフォームのシナリオのデータフローを示しています。

小売プラットフォームのユースケースのアーキテクチャ。

図 4. 小売プラットフォームのアーキテクチャの例。

データ変更のリアルタイム キャプチャ

このユースケースでは、アプリが、グローバル状態を変更するリアルタイムのユーザー入力を受け取ります。データポータルのダッシュボードから、リアルタイム イベントを追跡してユーザーの行動やインタラクションを詳しく把握できます。ユーザー アクションによりステータス値が更新されると、次のイベントが発生します。

  1. Firestore が、変更(新旧のステータス値を含む)を BigQuery に書き込む Cloud Functions の関数をトリガーします。
  2. データポータルのダッシュボードが、BigQuery のイベントデータに対してリアルタイム集計クエリを実行します。
  3. クエリは、異なるバケットに集約されたイベント変更の割合、タイムバケットごとの固有なイベントのタイプ、イベント取り込みレイテンシなどの指標を生成します。

このアーキテクチャの詳細なプレゼンテーションとデモについては、Cloud Next '19 の動画 Firestore で優れたアプリを構築するをご覧ください。

図 5 は、リアルタイムのデータ変更をキャプチャするためのアーキテクチャを示しています。

データ キャプチャのユースケースのアーキテクチャ。

図 5. シンプルなデータ キャプチャのアーキテクチャの例。

共同編集可能なコンテンツの編集

共同編集可能なコンテンツ管理システム(CMS)を使用すると、複数の編集者が同じ記事を同時に編集できるようになります。文字の追加や削除など、編集者が何かしらの変更を加えるたびに、編集者のクライアントにより変更が Firestore に直接書き込まれます。

複数の編集者が同時に変更を送信した場合、次の解決プロセスが発生します。

  1. Firestore のトランザクションにより、最初に受信した変更のみがデータベースに書き込まれます。その他の変更は拒否されます。
  2. Firestore は、更新されたコンテンツをすべての編集者に自動的に送信します。
  3. 最初に拒否された編集者は、更新されたコンテンツの上に自分の変更を再適用してから、変更を Firestore に再送信します。
  4. すべてのクライアントによるすべての変更が受け入れられ、データベースに書き込まれるまで、同じ競合解決プロセスが繰り返されます。

編集者はステージング パイプラインを使用して、コンテンツを次のようにプレビューできます。

  1. Cloud Scheduler でホストされている cron ジョブが、Cloud Functions の関数を 1 秒ごとにトリガーします。
  2. この関数は、Firestore から Cloud SQL でホストされているステージング データベースに最新のコンテンツをコピーします。
  3. 編集者は、App Engine でホストされているステージング サーバーでステージングされたコンテンツをプレビューします。

コンテンツが完成したら、編集者は CMS の公開ボタンをクリックします。このアクションにより、Firestore から最新のコンテンツを Cloud SQL でホストされている本番環境データベースにコピーする Cloud Functions の関数がトリガーされます。読者は、新しく公開されたコンテンツを本番環境のウェブサイトで利用できます。このアーキテクチャに似た実例については、New York Times の記事、ニュースルームの CMS 向けの共同編集を構築をご覧ください。

図 6 は、共同編集可能なコンテンツ編集のユースケースでコンテンツを編集、ステージング、公開するためのパイプラインを示しています。

コンテンツ編集のユースケースのアーキテクチャ。

図 6. 共同編集可能なコンテンツ編集プラットフォームのアーキテクチャの例。

次のステップ