コンテンツに移動
デベロッパー

Cloud Spanner での Active Record のサポートによる Ruby アプリケーションのスケーリング

2021年12月27日
Google Cloud Japan Team

※この投稿は米国時間 2021 年 12 月 11 日に、Google Cloud blog に投稿されたものの抄訳です。

このたび、Google Cloud Spanner 向け Ruby Active Record Adapter が一般提供されます。Ruby Active Record は、Ruby on Rails にバンドルされている強力なオブジェクト リレーショナル マッピング(ORM)ライブラリです。Active Record は、基盤となるデータベースを抽象化し、スキーマの変更を自動生成する機能やスキーマのバージョン履歴を管理する機能などを提供します。

Active Record は Rails プロジェクトで使用されるのが一般的ですが、Sinatra のような他のフレームワークで使用したり、Ruby アプリケーションのスタンドアロン ライブラリとして使用することもできます。このアダプタの一般提供により、Ruby アプリケーションでも、ORM を介して Cloud Spanner の高可用性と外部整合性を大規模に利用できるようになりました。

このアダプタは、Ruby の gem として ruby-spanner-activerecord という名前でリリースされています。現在サポートされているオプションは次のとおりです。

  • ActiveRecord 6.0.x と Ruby 2.6 および 2.7 の組み合わせ。

  • ActiveRecord 6.1.x と Ruby 2.6 以上の組み合わせ。

今回の投稿では、Rails アプリケーションでこのアダプタを使用する方法を説明し、サポートされている機能をご紹介します。

インストール

Cloud Spanner データベースで Active Record を使用するには、Cloud Spanner API を有効にしたアクティブな Google Cloud プロジェクトが必要です。Cloud Spanner の開始方法の詳細については、Cloud Spanner スタートガイドをご覧ください。

プロジェクトでは、既存の Cloud Spanner インスタンスを使用できます。既存のインスタンスがない場合や、新しい Ruby アプリケーション向けにゼロから始めたい場合は、Google Cloud SDK を使用して Cloud Spanner のインスタンスを作成できます。次に例を示します。

読み込んでいます...

アダプタをインストールするには、Rails アプリケーションの「Gemfile」を編集して、activerecord-spanner-adapter という名前の gem を追加します。

読み込んでいます...

次に、バンドルを実行して gem をインストールします。

読み込んでいます...

アダプタの構成

Rails アプリでは、Spanner のプロジェクト名、インスタンス名、データベース名を構成して、データベース アダプタを構成する必要があります。Cloud Spanner は Cloud Identity and Access Management を利用してユーザーやグループによるリソースへのアクセスを制御しているため、適切な権限を持つ Cloud サービス アカウントを使用してデータベースにアクセスできます。構成の変更は、Rails プロジェクトの config/database.yml ファイルで行います。

Cloud Spanner データベースの開発時やテスト時にコードをローカルで実行するには、アプリケーションのデフォルト認証情報で認証するか、GOOGLE_APPLICATION_CREDENTIALS  環境変数を設定し、サービス アカウントを使用して認証できます。このアダプタは、認証を Cloud Spanner の Ruby クライアント ライブラリに委任します。このライブラリや他のクライアント ライブラリをすでに正しく使用できている場合は、Ruby アプリケーションでの認証のために新たにすべきことは何もありません。詳細については、クライアント ライブラリのドキュメントで認証の設定をご覧ください。

クラウド上のデータベースを利用する以外に、Google の Cloud Spanner Emulator を利用することもできます。アダプタの受け入れテストは、エミュレータに対して実行されます。必要に応じて、Rakefile の構成を例として使用できます。

以下の例では、開発環境にサービス アカウント キーを使用しています。本番環境では、アプリケーションは、アプリケーションのデフォルトの認証情報を使用します。

読み込んでいます...

Spanner アダプタの使用方法

アダプタを構成した後は、Rails の標準ツールを使ってデータベースを作成し、管理できます。アダプタのリポジトリにある Rails チュートリアルに従って、クライアントが Cloud Spanner API とどのようにやり取りするかを見ていきます。

テーブルを持つデータベースの作成

まず、以下のコマンドを実行してデータベースを作成します。

読み込んでいます...

データモデルを生成するには、次のようにします。

読み込んでいます...

上記のコマンドを実行すると、以下のようなデータベース移行ファイルが生成されます。

読み込んでいます...

Active Record は、マイグレーションと呼ばれる強力なスキーマ バージョン管理システムを提供しています。それぞれのマイグレーションには、スキーマ変更につながる Active Record データモデルの変更が記述されます。Active Record は内部の「schema_migrations」テーブルでマイグレーションを追跡し、スキーマのバージョン間でデータを移行したり、アプリのモデルから自動的にマイグレーションを生成するツールを備えています。

上記のファイルでマイグレーションを実行すると、「title」と「body」という 2 つの列を持つ「articles」というテーブルが作成されます。

読み込んでいます...

マイグレーションが完了すると、GCP Cloud Spanner コンソールで Active Record によって作成されたテーブルを確認できます。

https://storage.googleapis.com/gweb-cloudblog-publish/images/tables_active_record.max-300x300.png

また、「information_schema.tables」を調べることで、Google Cloud SDK を使って Ruby が作成したテーブルを表示することもできます。

読み込んでいます...

Rails を用いたデータベースとのやり取り

データベースとテーブルが作成されると、コードの操作や、Rails CLI の使用が可能になります。CLI を使い始める場合: 

読み込んでいます...

このコマンドを実行すると、コマンド プロンプトが起動し、その中で Ruby のコードを実行できます。たとえば、「articles」テーブルにクエリを実行するには、次のクエリを実行します。

読み込んでいます...

「SELECT」という SQL クエリが内部で実行されていることがわかります。予想どおり、テーブルはまだ空なので、レコードは返されません。

プロンプトで、新しい「Article」オブジェクトを初期化し、そのオブジェクトをデータベースに保存できます。

読み込んでいます...

このアダプタがトランザクションを開始してデータベース テーブルに新しいレコードを挿入する SQL クエリを作成していることがわかります。

オブジェクトを確認すると、「id」、「created_at」、「updated_at」という項目が設定されているのがわかります。

読み込んでいます...

また、データベースの既存のレコードを修正することもできます。たとえば、「article」の本文を別のものに変更して、その変更を保存できます。

読み込んでいます...

このコードは、データベース内の値を変更するための「UPDATE」SQL ステートメントになります。この結果は、Spanner コンソールの「データ」ページで確認できます。

https://storage.googleapis.com/gweb-cloudblog-publish/images/spanner_console_data_page.max-500x500.png

アダプタはデータベースからデータを取得するための Active Record クエリ インターフェースをサポートしています。たとえば、以下のようなコードで、「title」や「id」で検索できます。両方とも、データを取り戻すために対応する SQL ステートメントを生成します。

読み込んでいます...

既存のデータベースの移行

Cloud Spanner の Active Record アダプタは、既存のデータベースの移行もサポートしています。

たとえば、既存のテーブルに 2 つの新しい列を追加したい場合は、「rails generate migration」コマンドを使って移行ファイルを作成します。

読み込んでいます...

このコマンドを実行すると、以下のような移行ファイルが作成されます。

読み込んでいます...

最後に、スキーマの変更を commit するために、「rails db:migrate」コマンドを実行します。

読み込んでいます...

もう一度、Spanner コンソールから変更を確認してみましょう。

https://storage.googleapis.com/gweb-cloudblog-publish/images/spanner_schema.max-500x500.png

移行をロールバックしたい場合には、「rails db:rollback」を実行します。移行の詳細については、Active Record Migrations ドキュメントをお読みください。移行を実行する前に、 Spanner スキーマ アップデートのドキュメントを確認することをおすすめします。

注目すべき特長

トランザクション サポート

データベースの読み取りや更新が必要な場合、複数のステートメントを一つのトランザクションにまとめたい場合があります。そのようなユースケースの場合は、この例のように手動で読み取り / 書き込みのトランザクションを制御できます。

書き込み操作を行わず、複数の一貫した読み取りのみを実行する必要がある場合は、この例のように読み取り専用のトランザクションを使用するとよいでしょう。

commit タイムスタンプ

Commit タイムスタンプの列は、この例で示されているように、モデル作成時に「:commit_timestamp」シンボルを使って構成できます。Commit タイムスタンプは、挿入や更新のトランザクションが完了した後に読み取ることができます。

ミューテーション

トランザクションの種類に応じて、アダプタは更新実行時にミューテーションDML のいずれかを自動的に選択します。効率化のため、可能な限り DML の代わりにミューテーションを使用しています。分離レベル「:buffered_mutations」を使って、アダプタにミューテーションの使用を明示的に指示する方法を知りたい場合は、  こちらの例をご覧ください。

クエリのヒント

Cloud Spanner はさまざまなステートメントのヒントテーブルのヒントをサポートしています。これらはアダプタでもサポートされています。この例では、「optimizer_hints」メソッドを使ってステートメントやテーブルのヒントを指定する方法を紹介します。また、例の中に結合のヒントがあります。この例では、メソッドを使うことはできませんが、代わりに結合文字列を使うことができます。

ステイル読み取り

Cloud Spanner には 2 種類の読み取りがあります。デフォルトでは、すべての読み取り専用のトランザクションが強力な読み取りを実行します。この例のように、明示的なタイムスタンプ バウンドを使用することで、データのクエリ時にステイル読み取りを行うようにできます。

生成列

Cloud Spanner は生成列をサポートしており、移行クラスで「as」キーワードを使って構成できます。この例では、どのように生成列が使用され、クラス内で「as」キーワードが使用されるかを示しています。

制限事項

アダプタにはいくつかの制限があります。たとえば、Cloud Spanner はシーケンス、ID 列、その他のデータベース内の値生成ツールをサポートしていないため、主キーの値を自動生成しません。テーブルに自然な主キーがない場合は、クライアントサイドの UUID 生成ツールを主キーに使用することをおすすめします。

このアダプタを使用するプロジェクトをデプロイする前に、制限事項の一覧を確認することをおすすめします。制限事項は、こちらに掲載されています。

また、Cloud Spanner エミュレータをお使いのお客様は、Cloud Spanner サービスとは異なる動作となることがあります。たとえば、エミュレータでは同時実行のトランザクションをサポートしていません。制限事項および Cloud Spanner サービスとの違いのリストについては、Cloud Spanner エミュレータのドキュメントをご覧ください。

知識を深める

特に、Cloud Spanner を検討している Rails ユーザーや、新規プロジェクトに Ruby の使用を検討されている Cloud Spanner の既存のお客様からのご意見をお待ちしています。このプロジェクトはオープンソースです。GitHub でコメント、バグレポート、pull リクエストを行うことができます。

このプロジェクトに携わってくださった Knut Olav Løite 氏Jiren Patel 氏に感謝いたします。

関連情報

始める前に、Rails プロジェクトを用意する必要があります。完全な例については、gem の GitHub リポジトリまたは以下をご覧ください。

関連記事

SQLAlchemy 向け Google Cloud Spanner 言語

Python SQLAlchemy アプリケーションで Google Cloud Spanner をデータベースとして使用できるようにする。

ソリューション アーキテクト Xiang Shen
投稿先