Memcache から Memorystore への移行

高パフォーマンスでスケーラブルな Python ウェブ アプリケーションでは、一部のタスクに堅牢な永続ストレージではなく、分散型のインメモリ データ キャッシュを使用することがよくあります。

この用途の App Engine ソリューションには Memcache があります。これは、特定のタスクのキャッシュとして使用される分散型インメモリ データストアです。

以前のバンドル サービスから移行する場合、App Engine Memcache の推奨代替サービスは Memorystore です。これはフルマネージド型のクラウドベースのキャッシュ サービスで、オープンソースのキャッシュ エンジン、Redis、Memcached をサポートします。このガイドでは、Memorystore for Redis の使用について説明します。これを使用すると、ミリ秒未満のデータアクセスを実現するアプリケーション キャッシュを構築できます。

Python アプリで Memcache を使用して ndb または Cloud NDB リクエストのレイテンシのみを削減する場合は、Memcache または Memorystore for Redis の代わりに、Cloud NDB の Redis 用組み込みサポートを使用できます。

使用を開始する前に、アプリが Memorystore for Redis の割り当ての範囲内にあることを確認してください。

Python アプリでメモリ キャッシュを使用するタイミング

Python アプリでは、セッション データ、ユーザー設定、ウェブページへのクエリで返されたその他のデータが、キャッシュの候補として適しています。通常、頻繁に実行されるクエリから返された結果が、アプリですぐに表示する必要がない場合は、結果をキャッシュに保存できます。後続のリクエストでは、キャッシュをチェックして、結果が存在しないか期限切れになっている場合にのみデータベースへのクエリを実行します。

永続ストレージにバックアップせずに Memorystore にのみ値を保存する場合は、値が期限切れになり、キャッシュから削除されたときに、アプリケーションが適切に動作することを確認してください。たとえば、ユーザーのセッション データが突然なくなったために、セッションが誤動作する場合、そのデータはおそらく Memorystore だけでなく、データベースにも保存する必要があると考えられます。

始める前に

まだ設定済みでない場合は、Google Cloud と互換性のある Python バージョンを使用するよう Python 開発環境を設定して、独立した Python を作成するためのテストツールをインストールします。

Memorystore の権限について確認する

Google Cloud サービスでのすべての操作について承認を得る必要があります。たとえば、Memorystore でホストされている Redis データベースを操作するには、アプリは Memorystore へのアクセス権を持つアカウントの認証情報を提供する必要があります。

デフォルトでは、App Engine のデフォルトのサービス アカウントの認証情報がアプリで提供されます。このアカウントには、アプリと同じプロジェクト内のデータベースにアクセスする権限があります。

次のいずれかの条件に当てはまる場合は、認証情報を明示的に提示する別の認証方法を使用する必要があります。

  • アプリと Memorystore データベースが異なる Google Cloud プロジェクトに属する。

  • デフォルトの App Engine サービス アカウントに割り当てられているロールが変更されている。

代替認証の方法については、サーバー間の本番環境アプリケーションの認証の設定をご覧ください。

移行プロセスの概要

Python アプリで Memcache の代わりに Memorystore を使用するには、次の手順を行います。

  1. Redis 用 Memorystore をセットアップします。そのためには、Memorystore で Redis インスタンスを作成し、アプリが Redis インスタンスとの通信に使用するサーバーレス VPC アクセスを作成する必要があります。この 2 つの独立したエンティティを作成する順序は厳密ではなく、どのような順序でも設定が可能です。このガイドでは、まずサーバーレス VPC アクセスを設定する手順について説明します。

  2. Redis のクライアント ライブラリをインストールし、Redis コマンドを使用してデータをキャッシュに保存します。

    Memorystore for Redis は Redis 用クライアント ライブラリと互換性があります。

    このガイドでは、アプリから Redis コマンドを送信する際の redis-py クライアント ライブラリの使用について説明します。

  3. 更新をテストします

  4. App Engine にアプリをデプロイする

Memorystore for Redis のセットアップ

Memorystore for Redis をセットアップするには:

  1. App Engine を VPC ネットワークに接続します。アプリは VPC コネクタを介してのみ Memorystore と通信できます。

    コネクタを使用するようにアプリを構成するの説明に沿って、app.yaml ファイルに VPC 接続情報を追加します。

  2. 作成する Redis インスタンスの IP アドレスとポート番号をメモします。この情報は、コードで Redis クライアントを作成するときに使用します。

  3. Memorystore で Redis インスタンスを作成します。

    Redis インスタンスのリージョンを選択するように求められたら、App Engine アプリが配置されているのと同じリージョンを選択します。

依存関係のインストール

redis-py クライアント ライブラリを使用するには、次の手順を実行します。

  1. app.yaml ファイルを更新します。Python のバージョンに応じた手順に沿って操作します。

    Python 2

    Python 2 アプリの場合は、grpcio ライブラリと setuptools ライブラリの最新バージョンを追加します。

    app.yaml ファイルの例を次に示します。

    runtime: python27
    threadsafe: yes
    api_version: 1
    
    libraries:
    - name: grpcio
      version: latest
    - name: setuptools
      version: latest
    

    Python 3

    Python 3 アプリの場合は、app.yaml ファイルの runtime 要素に、サポートされている Python 3 バージョンを指定します。次に例を示します。

    runtime: python310 # or another support version
    

    Python 3 ランタイムでは、ライブラリが自動的にインストールされるため、以前の Python 2 ランタイムの組み込みライブラリを指定する必要はありません。移行時に Python 3 アプリが他の以前のバンドル サービスを使用している場合は、引き続き必要な組み込みライブラリを指定できます。それ以外の場合は、app.yaml ファイル内の不要な行を削除してください。

  2. requirements.txt ファイルを更新します。Python のバージョンに応じた手順に沿って操作します。

    Python 2

    Memorystore for Redis 用の Cloud クライアント ライブラリを requirements.txt ファイルの依存関係のリストに追加します。

    redis
    

    pip install -t lib -r requirements.txt を実行して、アプリで使用可能なライブラリのリストを更新します。

    Python 3

    Memorystore for Redis 用の Cloud クライアント ライブラリを requirements.txt ファイルの依存関係のリストに追加します。

    redis
    

    Python 3 ランタイムにアプリをデプロイするときに、App Engine によってこれらの依存関係が自動的にインストールされるため、lib フォルダが存在する場合は削除します。

  3. Python 2 アプリの場合、lib ディレクトリで指定された組み込みライブラリまたはコピーされたライブラリをアプリで使用する場合は、それらのパスを app.yaml ファイルと同じフォルダにある appengine_config.py ファイル内で指定する必要があります。

    import pkg_resources
    from google.appengine.ext import vendor
    
    # Set PATH to your libraries folder.
    PATH = 'lib'
    # Add libraries installed in the PATH folder.
    vendor.add(PATH)
    # Add libraries to pkg_resources working set to find the distribution.
    pkg_resources.working_set.add_entry(PATH)
    

Redis クライアントの作成

Redis データベースを操作するには、コード内で Redis クライアントを作成し、Redis データベースへの接続を管理する必要があります。以下のセクションでは、redis-py クライアント ライブラリを使用した Redis クライアントの作成について説明します。

環境変数の指定

redis-py クライアント ライブラリは、2 つの環境変数を使用して Redis データベースの URL をアセンブルします。

  • Memorystore で作成した Redis データベースの IP アドレスを識別する変数。
  • Memorystore で作成した Redis データベースのポート番号を識別する変数。

コード内で直接定義するのではなく、アプリの app.yaml ファイル内でこれらの変数を定義することをおすすめします。これにより、ローカル環境や App Engine などのさまざまな環境でアプリを実行しやすくなります。

たとえば、app.yaml ファイルに次の行を追加します。

 env_variables:
      REDISHOST: '10.112.12.112'
      REDISPORT: '6379'

redis-py のインポートとクライアントの作成

REDISHOST 環境変数と REDISPORT 環境変数を定義した後に、次の行を使用して redis-py ライブラリをインポートしてクライアントを作成します。

  import redis

  redis_host = os.environ.get('REDISHOST', 'localhost')
  redis_port = int(os.environ.get('REDISPORT', 6379))
  redis_client = redis.Redis(host=redis_host, port=redis_port)

古いバージョンの redis-py をその他のアプリで使用している場合は、Client ではなく StrictClient クラスを使用しているかもしれません。ただし、redis-py では現在、StrictClient ではなく Client の使用をおすすめします。

Redis コマンドを使用したキャッシュへのデータの保存と取得

Memorystore Redis データベースではほとんどの Redis コマンドがサポートされています。キャッシュからのデータの保存と取得にはいくつかのコマンドが必要になります。次の表に、データのキャッシュに使用できる Redis コマンドを示します。アプリからこれらのコマンドを呼び出す方法については、クライアント ライブラリのドキュメントをご覧ください。

Python 2 アプリの場合、Memcache では多くのコマンドに非同期の代替メソッドが用意されていますが、redis-py クライアント ライブラリでは必ずしも同等の非同期メソッドは提供されません。キャッシュとのやりとりがすべて非同期である必要がある場合は、Python 用のその他の Redis クライアント ライブラリを使用してください。

タスク Redis コマンド
データ キャッシュにエントリを作成し、
エントリの有効期限を設定する
SETNX
MSETNX
キャッシュからデータを取得する GET
MGET
既存のキャッシュ値を置き換える SET
MSET
数値キャッシュ値を増減する INCR
INCRBY
DECR
DECRBY
キャッシュからエントリを削除する DEL
UNLINK
キャッシュとの並行処理をサポートする(比較と設定 Redis トランザクションの詳細をご覧ください。redis-py クライアント ライブラリでは、すべてのトランザクションがパイプラインで発生する必要があります。

アップデートのテスト

アプリをローカルでテストする場合は、Redis のローカル インスタンスを実行して、本番環境用データとの通信を回避してください(Memorystore では、エミュレータは提供されません)。Redis をローカルにインストールして実行するには、Redis のドキュメントにある手順を行ってください。現在、Redis を Windows 上でローカルに実行することはできません。

Python アプリのテストについて詳しくは、ローカルの開発用サーバーの使用をご覧ください。

アプリのデプロイ

アプリをローカル開発用サーバーでエラーなしで実行した場合は、次の手順を行います。

  1. App Engine でアプリをテストします。

  2. アプリがエラーなしで実行されている場合、トラフィック分割を使用して、更新したアプリのトラフィックを徐々に増やします。更新したアプリへのトラフィックを増やす前に、データベースの問題が発生していないか細かくアプリをモニタリングして確認してください。

次のステップ