Memorystore を使用したデータのキャッシュ

高パフォーマンスでスケーラブルなウェブ アプリケーションでは多くの場合、一部のタスクの処理に、堅牢で永続的なストレージに優先して(あるいはその代わりに)分散型のインメモリ データ キャッシュを使用します。Memorystore for Redis をキャッシュ サービスとして使用することをおすすめします。Memorystore for Redis に無料枠はありません。詳細は、Memorystore の料金をご覧ください。

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

メモリ キャッシュの用途

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

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

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

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

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

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

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

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

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

Memorystore の使用方法の概要

アプリで Memorystore を使用するには:

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

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

    Memorystore for Redis は Redis 用クライアント ライブラリと互換性があります。このガイドでは、アプリから Redis コマンドを送信する際の redigo クライアント ライブラリの使用について説明します。

  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 アプリが配置されているのと同じリージョンを選択します。

依存関係のインストール

アプリが App Engine で実行されているときに、redigo クライアント ライブラリをアプリで使用できるようにするには、ライブラリをアプリの依存関係に追加します。たとえば、go.mod ファイルを使用して依存関係を宣言するには、次の行を go.mod ファイルに追加します。

module github.com/GoogleCloudPlatform/golang-samples/tree/master/memorystore/redis

詳細については、Go アプリの依存関係の指定をご覧ください。

Redis クライアントの作成

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

環境変数の指定

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

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

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

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

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

redigo のインポートとクライアントの作成

REDISHOST 環境変数と REDISPORT 環境変数を定義したら、次の行を使用して、redigo ライブラリをインポートし、接続プールを作成して、プールから Redis クライアントを取得します。


// Command redis is a basic app that connects to a managed Redis instance.
package main

import (
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/gomodule/redigo/redis"
)

var redisPool *redis.Pool

func incrementHandler(w http.ResponseWriter, r *http.Request) {
	conn := redisPool.Get()
	defer conn.Close()

	counter, err := redis.Int(conn.Do("INCR", "visits"))
	if err != nil {
		http.Error(w, "Error incrementing visitor counter", http.StatusInternalServerError)
		return
	}
	fmt.Fprintf(w, "Visitor number: %d", counter)
}

func main() {
	redisHost := os.Getenv("REDISHOST")
	redisPort := os.Getenv("REDISPORT")
	redisAddr := fmt.Sprintf("%s:%s", redisHost, redisPort)

	const maxConnections = 10
	redisPool = &redis.Pool{
		MaxIdle: maxConnections,
		Dial:    func() (redis.Conn, error) { return redis.Dial("tcp", redisAddr) },
	}

	http.HandleFunc("/", incrementHandler)

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}
	log.Printf("Listening on port %s", port)
	if err := http.ListenAndServe(":"+port, nil); err != nil {
		log.Fatal(err)
	}
}

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

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

タスク Redis コマンド
データ キャッシュにエントリを作成し、
エントリの有効期限を設定する
SETNX
MSETNX
キャッシュからデータを取得する GET
MGET
既存のキャッシュ値を置き換える SET
MSET
数値キャッシュ値を増減する INCR
INCRBY
DECR
DECRBY
キャッシュからエントリを削除する DEL
UNLINK
キャッシュとの並行処理をサポートする Redis トランザクションの詳細をご覧ください。

アップデートのテスト

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

アプリのデプロイ

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

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

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